Objective-C中的#define vs const
我是Objective-C的新手,我有几个关于const
和预处理指令#define
。
首先,我发现使用#define
定义常量的types是不可能的。 这是为什么?
其次,使用其中一个有什么好处?
最后,哪种方式更有效率和/或更安全?
首先,我发现它不可能使用#define定义常量的types,为什么呢?
为什么是什么? 这不是真的:
#define MY_INT_CONSTANT ((int) 12345)
其次,使用其中一个有什么好处?
是。 #define
定义了一个在编译开始之前被replace的macros。 const
只是修改一个variables,以便编译器会在你尝试修改的时候标记一个错误。 有些情况下你可以使用#define
但是你不能使用const
(虽然我正在努力寻找一个使用最新的clang)。 理论上, const
在可执行文件中占用空间并需要对内存的引用,但实际上这并不重要,可能会被编译器优化掉。
const
比#define
更适合编译器和debugging器。 在大多数情况下,在决定使用哪一个时,这是您应该考虑的重点。
只是想到你可以使用#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;
在标题中。 除了定义的C文件外, MY_INT_CONST
不能用作任何C文件中静态或全局作用域数组的大小。
但是,对于整数常量,您可以使用enum
。 事实上,苹果几乎总是这样做。 这具有#define
s和const
s的所有优点,但只适用于整数常量。
// 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标准它是正式的未定义行为。
就个人而言,对于整数常量,我总是使用enum
的其他types的const
,我使用const
除非我有一个非常好的理由不。
从C编码器:
const
是一个简单的variables,其内容不能改变。
但是,# #define name value
是一个预处理器命令,用value
replacename
所有实例。
例如,如果你#define defTest 5
,那么你编译时,你的代码中所有的defTest
实例将被replace为5
。
理解#define和const指令之间的区别是非常重要的。
const
const
用于从被问询的types生成一个对象,一旦初始化,该对象将保持不变。 这意味着它是程序存储器中的一个对象,可以作为只读使用。 每次程序启动时都会生成该对象。
#define
#define
用于简化代码的可读性和将来的修改。 当使用一个定义时,你只能掩盖一个名字后面的值。 因此,在使用矩形时,可以使用相应的值定义宽度和高度。 然后在代码中,它会更容易阅读,因为代替数字会有名字。
如果以后你决定改变宽度的值,你只需要在定义中改变它,而不是在你的整个文件中进行无聊和危险的查找/replace。 编译时,预处理器将用代码中的值replace所有定义的名称。 因此,没有时间使用它们。
除了其他人的评论之外,使用#define
错误是非常难以debugging的,因为预处理器在编译器之前掌握了这些错误。
由于预处理器指令是皱眉,我build议使用const
。 您无法使用预处理器指定types,因为在编译之前会parsing预处理器指令。 那么,你可以,但是像这样:
#define DEFINE_INT(name,value) const int name = value;
并将其用作
DEFINE_INT(x,42)
这将被编译器看作
const int x = 42;
首先,我发现它不可能使用#define定义常量的types,为什么呢?
你可以看到我的第一个片段。
其次,使用其中一个有什么好处?
通常有一个const
而不是预处理器指令有助于debugging,而不是在这种情况下(但仍然)。
最后,哪种方式更有效率和/或更安全?
两者都是有效的。 我会说macros可能会更安全,因为它不能在运行时更改,而variables可以。
我曾经使用过#define来帮助创build更多的方法,如果我有类似的东西。
// 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)
我认为这是一件非常酷的事情,我知道你可以直接使用这个方法,只在你不想要的空间中放入零,但是如果你正在build立一个库,它是非常有用的。 这也是如何
NSLocalizedString(<#key#>, <#comment#>) NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>) NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)
完成。
而我不相信你可以用常量做到这一点。 但是常量比#define有更多的好处,就像你不能用#define指定一个types一样,因为它是一个在编译之前解决的预处理器指令,如果你在#define中遇到错误,那么它们就很难debugging常量。 两者都有好处和坏处,但我要说这一切都取决于程序员你决定使用哪一个。 我已经写了一个库,他们在使用#define做我已经显示和常量声明常量variables,我需要指定一个types。