常量解释

发布于 2024-10-06 11:42:03 字数 176 浏览 3 评论 0原文

我一直在寻找常量,除了不能以编程方式更改之外,我真的不明白它们有什么不同。

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁月染过的梦 2024-10-13 11:42:03

这里会问你两个问题:一是关于常量,一是关于 extern。两者没有必然联系。

首先,const:正如您所说,常量没有什么比它们不能以编程方式更改的更多内容了。不过,不同的事物可以保持不变,具体取决于您如何声明它们。例如,在您的示例中:

NSString * const MyConstant = @"foo";

您声明了一个指向非常量 NSString 对象的常量指针; const 关键字位于星号的右侧,因此它指的是指针。因此, this:

MyConstant = @"bar";

会导致编译错误,因为它试图重新分配 MyConstant 以指向不同的 NSString。

如果 const 关键字位于星号的左侧,它将引用指针引用的对象(在本例中为底层 NSString 结构)。在 Objective C 中,这可能不是您大多数时候想要的。请注意,const 关键字相对于类型标识符的位置并不重要,因此 this:

const NSString *MyConstant = @"foo";

和 this:

NSString const *MyConstant = @"foo";

含义相同事物。您还可以合法地将指针和引用值声明为 const,以获得最大 constness:

const NSString * const MyConstant = @"foo";

其次,externextern 只是允许您在一个编译单元中声明一个变量,并且让编译器知道您已在单独的编译单元中定义了该变量。通常,您只会将其用于全局值和常量。

您可以将编译单元视为单个 .m 文件,以及它包含的所有 .h 文件。在构建时,编译器将每个 .m 文件编译为单独的 .o 文件,然后链接器将它们全部挂接到一个二进制文件中。通常,一个编译单元了解在另一编译单元中声明的标识符(例如类名)的方式是通过导入头文件。但是,对于全局变量,它们通常不是类的公共接口的一部分,因此它们经常在 .m 文件中声明和定义。

如果编译单元 A 在 .m 文件中声明了一个全局变量:

#import "A.h"

NSString *someGlobalValue;

并且编译单元 B 想要使用该全局变量:

#import "B.h"
extern NSString *someGlobalValue;

@implementation B

- (void)someFunc {
    NSString *localValue = [self getSomeValue];
    if (localValue isEqualToString:someGlobalValue]) {
        ...
    }
}

单元 B 必须以某种方式告诉编译器使用单元 A 声明的变量。它可以' t 导入发生声明的 .m 文件,因此它使用 extern 告诉编译器该变量存在于其他地方。

请注意,如果单元 A 和单元 B 在文件的顶层都有此行:

NSString *someGlobalValue;

那么您有两个编译单元声明相同的全局变量,并且链接器将因重复符号错误而失败。如果您希望像这样的变量存在于编译单元内部,并且对任何其他编译单元不可见(即使它们使用extern),您可以使用static 关键字:

static NSString * const someFileLevelConstant = @"wibble";

这对于您想要在单个实现文件中使用但在其他地方不需要的常量非常有用。

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:

NSString * const MyConstant = @"foo";

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:

MyConstant = @"bar";

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 the const keyword relative to the type identifier doesn't matter, so this:

const NSString *MyConstant = @"foo";

and this:

NSString const *MyConstant = @"foo";

mean the same thing. You can also legally declare both the pointer and the referenced value const, for maximum constness:

const NSString * const MyConstant = @"foo";

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:

#import "A.h"

NSString *someGlobalValue;

and compilation unit B wants to use that global:

#import "B.h"
extern NSString *someGlobalValue;

@implementation B

- (void)someFunc {
    NSString *localValue = [self getSomeValue];
    if (localValue isEqualToString:someGlobalValue]) {
        ...
    }
}

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 uses extern 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:

NSString *someGlobalValue;

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 the static keyword:

static NSString * const someFileLevelConstant = @"wibble";

This can be useful for constants that you want to use within a single implementation file, but won't need elsewhere.

往日情怀 2024-10-13 11:42:03
extern NSString * const MyConstant;

您将在头文件中看到这一点。它告诉编译器变量 MyConstant 存在并且可以在您的实现文件中使用。

该变量的设置很可能类似于:

NSString * const MyConstant = @"foo";

该值无法更改。如果您想要一个可以更改的全局变量,请从声明中删除 const

extern NSString * const MyConstant;

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:

NSString * const MyConstant = @"foo";

The value can't be changed. If you want a global that can be changed, then drop the const from the declaration.

梦魇绽荼蘼 2024-10-13 11:42:03

Extern 意味着变量在声明它的源文件之外设置。建议使用 OBJC_EXPORT 标志而不是 extern。

const 表示变量设置后不能更改。但是,您可以使用一些指针错误方向,如下所示:

NSString **var = (NSString **)&MyConstant;
*var = @"I changed it!";

如果需要的话,这实际上允许您更改它(例如在您的类 +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:

NSString **var = (NSString **)&MyConstant;
*var = @"I changed it!";

That will actually allow you to change it, if you need to (e.g. in your classes +initialize method).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文