我刚接触Objective-C,关于const
和预处理指令#define
有几个问题。
首先,我发现无法使用 #define
定义常量的类型。这是为什么?
其次,它们之间是否有任何优势?
最后,哪种方法更有效和/或更安全?
我刚接触Objective-C,关于const
和预处理指令#define
有几个问题。
首先,我发现无法使用 #define
定义常量的类型。这是为什么?
其次,它们之间是否有任何优势?
最后,哪种方法更有效和/或更安全?
首先,我发现使用 #define 定义常量时无法指定其类型,为什么?
为什么什么?这不是真的:
#define MY_INT_CONSTANT ((int) 12345)
第二个问题是一个比较,是否有一个优于另一个的使用方式?// in a C file
const int MY_INT_CONST = 12345;
// in a header
extern const int MY_INT_CONST;
在头文件中,MY_INT_CONST
不能在除了它被定义的文件之外的任何C文件中作为静态或全局范围数组的大小。
然而,对于整数常量,您可以使用 enum
。事实上,这几乎是苹果公司经常采用的方法。这具有 #define 和 const 的所有优点,但仅适用于整数常量。
// In a header
enum
{
MY_INT_CONST = 12345,
};
最后,哪种方法更有效和/或更安全?
#define
在理论上更有效,尽管现代编译器可能会确保没有太大的区别。#define
更安全,因为试图对其进行赋值总是会导致编译错误。
#define FOO 5
// ....
FOO = 6; // Always a syntax error
const
变量可能会被欺骗并进行赋值,尽管编译器可能会发出警告:
const int FOO = 5;
// ...
(int) FOO = 6; // Can make this compile
根据所在平台的不同,如果将常量放置在一个只读段中,赋值可能在运行时失败,并且根据C标准,这是正式未定义的行为。
就整数常量而言,我个人总是使用enum
来定义常量,对于其他类型的常量,除非有很好的理由否则我会使用 const
。
来自一位C语言编码者:
const
只是一个变量,其内容不能被更改。
然而,#define name value
是一个预处理器命令,它将所有的name
实例替换为value
。
例如,如果您使用#define defTest 5
,则编译时代码中所有defTest
的实例都将被替换为5
。
理解#define和const两个指令的区别非常重要,它们并不是用于相同的事情。
const
const
用于生成一个在初始化后将是常量的所请求类型的对象。这意味着它是程序内存中的一个对象,并且可以被用作只读。
该对象在每次程序启动时生成。
#define
#define
用于简化代码的可读性和未来的修改。使用define时,您只需在名称后面掩盖一个值。因此,在处理矩形时,您可以定义相应值的宽度和高度。然后,在代码中,它将更容易阅读,因为名称而不是数字。
如果以后您决定更改宽度的值,则只需在define中更改它,而不是在整个文件中进行乏味和危险的查找/替换。 编译时,预处理程序将在代码中将所有定义的名称替换为其值。因此,使用它们没有时间上的损失。
除了其他人的评论外,使用#define
存在的错误通常很难调试,因为预处理器会在编译器之前占用它们。
由于预处理器指令并不被推荐使用,我建议使用const
。在预处理器之前解析预处理器指令时,无法指定类型。虽然你可以这样做,但是:
#define DEFINE_INT(name,value) const int name = value;
DEFINE_INT(x,42)
编译器会将其视为
const int x = 42;
const ...
而使用宏呢? - Ed Heal我以前使用过 #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 编写了一个包含两者的库,用于执行所示操作,并使用常量声明需要指定类型的常量变量。
int
一样大。然而,在现代编译器中,我非常惊讶它是否会有任何影响。 - JeremyP