【发布时间】:2012-06-24 13:45:03
【问题描述】:
我是 Objective-C 的新手,我有几个关于 const 和预处理指令 #define 的问题。
首先,我发现使用#define 定义常量的类型是不可能的。这是为什么呢?
其次,使用其中一个比另一个有什么优势吗?
最后,哪种方式更高效和/或更安全?
【问题讨论】:
标签: objective-c constants c-preprocessor
我是 Objective-C 的新手,我有几个关于 const 和预处理指令 #define 的问题。
首先,我发现使用#define 定义常量的类型是不可能的。这是为什么呢?
其次,使用其中一个比另一个有什么优势吗?
最后,哪种方式更高效和/或更安全?
【问题讨论】:
标签: objective-c constants c-preprocessor
了解#define 和 const 指令之间的区别很重要,它们并不意味着相同的事情。
constconst 用于从请求的类型生成一个对象,一旦初始化,该对象将是常量。这意味着它是程序内存中的一个对象,可以作为只读的。
每次启动程序时都会生成该对象。
#define#define 用于简化代码的可读性和未来的修改。使用定义时,您只需要在名称后面屏蔽一个值。因此,在使用矩形时,您可以使用相应的值定义宽度和高度。然后在代码中,它会更容易阅读,因为将有名称而不是数字。
如果稍后您决定更改宽度值,您只需在定义中更改它,而不是在整个文件中进行无聊且危险的查找/替换。 编译时,预处理器会将所有定义的名称替换为代码中的值。因此,使用它们不会浪费时间。
【讨论】:
来自 C 程序员:
const 只是一个变量,其内容无法更改。
然而,#define name value 是一个预处理器命令,它将所有 name 实例替换为 value。
例如,如果您#define defTest 5,那么您的代码中所有defTest 的实例都将在您编译时替换为5。
【讨论】:
我以前使用过#define 来帮助从一种方法中创建更多方法,例如我有类似的方法。
// This method takes up to 4 numbers, we don't care what the method does with these numbers.
void doSomeCalculationWithMultipleNumbers:(NSNumber *)num1 Number2:(NSNumber *)num2 Number3:(NSNumber *)num23 Number3:(NSNumber *)num3;
但我也有什么方法只需要 3 个数字和 2 个数字,所以我将使用 #define 来使用相同的方法,而不是编写两个新方法,就像这样。
#define doCalculationWithFourNumbers(num1, num2, num3, num4) \
doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), (num4))
#define doCalculationWithThreeNumbers(num1, num2, num3) \
doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), nil)
#define doCalculationWithTwoNumbers(num1, num2) \
doSomeCalculationWithMultipleNumbers((num1), (num2), nil, nil)
我认为这是一件很酷的事情,我知道您可以直接使用该方法并将 nil 放在您不想要的空间中,但是如果您正在构建一个库,它非常有用。也是这样的
NSLocalizedString(<#key#>, <#comment#>)
NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>)
NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)
完成了。
而我不相信你可以用常量做到这一点。但是常量确实比#define 有好处,就像你不能用#define 指定一个类型,因为它是一个在编译之前解析的预处理器指令,如果你在#define 中遇到错误,那么它们就更难调试了常数。两者都有优点和缺点,但我想说这完全取决于你决定使用哪个程序员。我已经用它们编写了一个库,使用#define 来执行我所展示的操作,并使用常量来声明我需要指定类型的常量变量。
【讨论】:
首先,我发现用#define定义常量的类型是不可能的,这是为什么呢?
为什么是什么?这不是真的:
#define MY_INT_CONSTANT ((int) 12345)
其次,使用其中一个比另一个有什么优势吗?
是的。 #define 定义了一个宏,它甚至在编译开始之前就被替换了。 const 只是修改一个变量,以便在您尝试更改它时编译器会标记错误。在某些情况下,您可以使用#define,但不能使用const(尽管我正在努力寻找一个使用最新的clang)。理论上,const 会占用可执行文件中的空间并需要对内存的引用,但实际上这无关紧要,并且可能会被编译器优化掉。
consts 比#defines 对编译器和调试器更友好。在大多数情况下,这是您在决定使用哪一个时应该考虑的最重要的一点。
刚刚想到一个可以使用#define 但不能使用const 的上下文。如果你有一个常量要在很多.c 文件中使用,使用#define 你只需将它放在标题中。使用const,您必须在 C 文件中有一个定义,并且
// in a C file
const int MY_INT_CONST = 12345;
// in a header
extern const int MY_INT_CONST;
在标题中。 MY_INT_CONST 不能用作任何 C 文件中的静态或全局范围数组的大小,但定义它的文件除外。
但是,对于整数常量,您可以使用enum。事实上,这就是苹果几乎一成不变的做法。这具有#defines 和consts 的所有优点,但仅适用于整数常量。
// In a header
enum
{
MY_INT_CONST = 12345,
};
最后,哪种方式更高效和/或更安全?
#define 在理论上更有效,尽管正如我所说,现代编译器可能确保几乎没有区别。 #define 更安全,因为尝试分配给它总是编译器错误
#define FOO 5
// ....
FOO = 6; // Always a syntax error
consts 可以被欺骗,尽管编译器可能会发出警告:
const int FOO = 5;
// ...
(int) FOO = 6; // Can make this compile
根据平台的不同,如果常量放置在只读段中并且根据 C 标准它是官方未定义的行为,则赋值可能在运行时仍然失败。
就个人而言,对于整数常量,我总是将enums 用于其他类型的常量,除非我有充分的理由不使用,否则我使用const。
【讨论】:
int。但是,如果它在现代编译器中产生任何影响,我会感到非常惊讶。
由于预处理器指令不受欢迎,我建议使用const。您不能使用预处理器指定类型,因为预处理器指令在编译之前已解析。好吧,你可以,但类似:
#define DEFINE_INT(name,value) const int name = value;
并将其用作
DEFINE_INT(x,42)
编译器会将其视为
const int x = 42;
首先,我发现不能用#define定义常量的类型,这是为什么呢?
你可以,看看我的第一个sn-p。
其次,使用其中一个比另一个有什么优势吗?
通常使用 const 而不是预处理器指令有助于调试,但在这种情况下作用不大(但仍然如此)。
最后,哪种方式更高效和/或更安全?
两者都一样有效。我想说宏可能可能更安全,因为它不能在运行时更改,而变量可以。
【讨论】:
const ... 而不是使用宏?
pre-processor directives are frowned upon [需要引用]
除了其他人的 cmets,使用 #define 的错误是出了名的难以调试,因为预处理器会在编译器之前获取它们。
【讨论】: