我是 Objective-C 的新手,我有一些关于const
preprocessing 指令的问题#define
。
首先,我发现无法使用#define
. 这是为什么?
其次,使用其中一个比另一个有什么优势吗?
最后,哪种方式更有效和/或更安全?
我是 Objective-C 的新手,我有一些关于const
preprocessing 指令的问题#define
。
首先,我发现无法使用#define
. 这是为什么?
其次,使用其中一个比另一个有什么优势吗?
最后,哪种方式更有效和/或更安全?
首先,我发现使用#define 定义常量的类型是不可能的,这是为什么呢?
为什么是什么?这不是真的:
#define MY_INT_CONSTANT ((int) 12345)
其次,使用其中一个比另一个有什么优势吗?
是的。 #define
定义了一个宏,它甚至在编译开始之前就被替换了。 const
仅修改一个变量,以便在您尝试更改它时编译器将标记错误。在某些情况下,您可以使用 a#define
但不能使用 a const
(尽管我正在努力使用最新的 clang 来寻找一个)。理论上,aconst
会占用可执行文件中的空间并需要对内存的引用,但实际上这无关紧要,并且可能会被编译器优化掉。
const
s 比#define
s 对编译器和调试器更友好。在大多数情况下,这是您在决定使用哪一个时应该考虑的最重要的一点。
只是想到了一个可以使用#define
但不能使用的上下文const
。如果您有一个要在大量.c
文件中使用的常量,#define
只需将其粘贴在标题中即可。使用 aconst
你必须在 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
. 事实上,这就是苹果几乎一成不变的做法。这具有#define
s 和const
s 的所有优点,但仅适用于整数常量。
// In a header
enum
{
MY_INT_CONST = 12345,
};
最后,哪种方式更有效和/或更安全?
#define
理论上更有效,尽管正如我所说,现代编译器可能确保几乎没有区别。 #define
更安全,因为尝试分配给它总是一个编译器错误
#define FOO 5
// ....
FOO = 6; // Always a syntax error
const
尽管编译器可能会发出警告,但 s 可能会被欺骗:
const int FOO = 5;
// ...
(int) FOO = 6; // Can make this compile
根据平台的不同,如果常量放置在只读段中并且根据 C 标准它是官方未定义的行为,则分配可能在运行时仍然失败。
就个人而言,对于整数常量,我总是将enum
s 用于其他类型的常量,const
除非我有充分的理由不使用。
来自 C 编码器:
Aconst
只是一个变量,其内容不能更改。
#define name value
然而,是一个预处理器命令,它用 替换所有name
实例value
。
例如,如果您是 ,则您的代码中的#define defTest 5
所有实例都将在您编译时defTest
替换为5
。
了解#define 和 const 指令之间的区别很重要,它们并不意味着相同的事情。
const
const
用于从所要求的类型生成一个对象,一旦初始化,该对象将是常量。这意味着它是程序内存中的一个对象,可以作为只读的。每次启动程序时都会生成该对象。
#define
#define
用于简化代码的可读性和未来的修改。使用定义时,您只需要在名称后面屏蔽一个值。因此,在使用矩形时,您可以使用相应的值定义宽度和高度。然后在代码中,它将更容易阅读,因为将有名称而不是数字。
如果稍后您决定更改宽度的值,您只需在定义中更改它,而不是在整个文件中进行无聊且危险的查找/替换。编译时,预处理器会将所有定义的名称替换为代码中的值。因此,使用它们不会浪费时间。
除了其他人的评论之外,#define
由于预处理器在编译器之前获取它们,因此使用错误是非常难以调试的。
由于预处理器指令不受欢迎,我建议使用const
. 您不能使用预处理器指定类型,因为预处理器指令在编译之前已解析。好吧,你可以,但类似:
#define DEFINE_INT(name,value) const int name = value;
并将其用作
DEFINE_INT(x,42)
编译器会将其视为
const int x = 42;
首先,我发现使用#define 定义常量的类型是不可能的,这是为什么呢?
你可以,看看我的第一个片段。
其次,使用其中一个比另一个有什么优势吗?
通常有一个const
而不是预处理器指令有助于调试,在这种情况下没有那么多(但仍然如此)。
最后,哪种方式更有效和/或更安全?
两者都一样有效。我想说宏可能更安全,因为它在运行时无法更改,而变量可以。
我之前使用过#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 来执行我所展示的操作,并使用常量来声明我需要指定类型的常量变量。