常量解释
我一直在寻找常量,除了不能以编程方式更改之外,我真的不明白它们有什么不同。
extern NSString * const MyConstant;
在这一行中,extern
到底意味着什么,const
究竟意味着什么?
I have been looking about constants and I don't really understand whats different about them other than they cant be changed programmatically.
extern NSString * const MyConstant;
With this line what exactly does extern
mean and what exactly does the const
mean?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里会问你两个问题:一是关于常量,一是关于 extern。两者没有必然联系。
首先,const:正如您所说,常量没有什么比它们不能以编程方式更改的更多内容了。不过,不同的事物可以保持不变,具体取决于您如何声明它们。例如,在您的示例中:
您声明了一个指向非常量 NSString 对象的常量指针;
const
关键字位于星号的右侧,因此它指的是指针。因此, this:会导致编译错误,因为它试图重新分配 MyConstant 以指向不同的 NSString。
如果 const 关键字位于星号的左侧,它将引用指针引用的对象(在本例中为底层 NSString 结构)。在 Objective C 中,这可能不是您大多数时候想要的。请注意,
const
关键字相对于类型标识符的位置并不重要,因此 this:和 this:
含义相同事物。您还可以合法地将指针和引用值声明为 const,以获得最大 constness:
其次,extern:
extern
只是允许您在一个编译单元中声明一个变量,并且让编译器知道您已在单独的编译单元中定义了该变量。通常,您只会将其用于全局值和常量。您可以将编译单元视为单个
.m
文件,以及它包含的所有.h
文件。在构建时,编译器将每个 .m 文件编译为单独的 .o 文件,然后链接器将它们全部挂接到一个二进制文件中。通常,一个编译单元了解在另一编译单元中声明的标识符(例如类名)的方式是通过导入头文件。但是,对于全局变量,它们通常不是类的公共接口的一部分,因此它们经常在.m
文件中声明和定义。如果编译单元 A 在
.m
文件中声明了一个全局变量:并且编译单元 B 想要使用该全局变量:
单元 B 必须以某种方式告诉编译器使用单元 A 声明的变量。它可以' t 导入发生声明的
.m
文件,因此它使用extern
告诉编译器该变量存在于其他地方。请注意,如果单元 A 和单元 B 在文件的顶层都有此行:
那么您有两个编译单元声明相同的全局变量,并且链接器将因重复符号错误而失败。如果您希望像这样的变量仅存在于编译单元内部,并且对任何其他编译单元不可见(即使它们使用
extern
),您可以使用static
关键字:这对于您想要在单个实现文件中使用但在其他地方不需要的常量非常有用。
You're asked two questions here: one about constants and one about extern. The two aren't necessarily related.
First, const: there isn't much more to constants than, as you said, they can't be changed programmatically. Different things can be constant though, depending on how you declare them. For instance, in your example:
you have declared a constant pointer to a non-constant NSString object; the
const
keyword is to the right of the star, so it refers to the pointer. Thus, this:would result in a compile error, since it's attempting to reassign
MyConstant
to point to a different NSString.If the
const
keyword were to the left of the star it would refer to the object the pointer references (in this case, the underlying NSString struct). This probably isn't what you want most of the time in Objective C. Note that the position of theconst
keyword relative to the type identifier doesn't matter, so this:and this:
mean the same thing. You can also legally declare both the pointer and the referenced value const, for maximum constness:
Second, extern:
extern
simply allows you to declare a variable in one compilation unit, and let the compiler know that you've defined that variable in a separate compilation unit. You would generally use this only for global values and constants.You can think of a compilation unit as a single
.m
file, as well as all the.h
files it includes. At build time the compiler compiles each .m file into a separate.o
file, and then the linker hooks them all together into a single binary. Usually the way one compilation unit knows about identifiers (such as a class name) declared in another compilation unit is by importing a header file. But, in the case of globals, they are often not part of a class's public interface, so they're frequently declared and defined in a.m
file.If compilation unit A declares a global in a
.m
file:and compilation unit B wants to use that global:
unit B has to somehow tell the compiler to use the variable declared by unit A. It can't import the
.m
file where the declaration occurs, so it usesextern
to tell the compiler that the variable exists elsewhere.Note that if unit A and unit B both have this line at the top level of the file:
then you have two compilation units declaring the same global variable, and the linker will fail with a duplicate symbol error. If you want to have a variable like this that exists only inside a compilation unit, and is invisible to any other compilation units (even if they use
extern
), you can use thestatic
keyword:This can be useful for constants that you want to use within a single implementation file, but won't need elsewhere.
您将在头文件中看到这一点。它告诉编译器变量
MyConstant
存在并且可以在您的实现文件中使用。该变量的设置很可能类似于:
该值无法更改。如果您想要一个可以更改的全局变量,请从声明中删除
const
。You'll see this in header files. It tells the compiler that the variable
MyConstant
exists and can be used in your implementation files.More likely than not, the variable is set something like:
The value can't be changed. If you want a global that can be changed, then drop the
const
from the declaration.Extern 意味着变量在声明它的源文件之外设置。建议使用 OBJC_EXPORT 标志而不是 extern。
const 表示变量设置后不能更改。但是,您可以使用一些指针错误方向,如下所示:
如果需要的话,这实际上允许您更改它(例如在您的类
+initialize
方法中)。Extern means that the variable is set outside the source file it was declared in. It is recommended to use the OBJC_EXPORT flag instead of extern.
Const means that the variable cannot be changed after being set. However, you can Use some pointer misdirection as shown below:
That will actually allow you to change it, if you need to (e.g. in your classes
+initialize
method).