常量的解释

时间:2010-12-04 16:06:25

标签: objective-c constants

我一直在寻找常量,除了不能以编程方式进行更改之外,我并不了解它们的不同之处。

extern NSString * const MyConstant;

有了这一行,extern究竟是什么意思,const究竟是什么意思?

3 个答案:

答案 0 :(得分:19)

这里有两个问题:一个关于常数,一个关于外部问题。这两者不一定相关。

首先, const :正如你所说的那样,常量并不多,它们不能以编程方式进行更改。不同的东西可以是不变的,这取决于你如何声明它们。例如,在您的示例中:

NSString * const MyConstant = @"foo";

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

MyConstant = @"bar";

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

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

const NSString *MyConstant = @"foo";

和此:

NSString const *MyConstant = @"foo";

意思是同样的事情。您还可以合法地声明指针和引用的值const,以获得最大的常量:

const NSString * const MyConstant = @"foo";

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

您可以将编译单元视为单个.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声明的变量。它不能导入声明发生的.m文件,所以它使用extern告诉编译器变量存在于其他地方。

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

NSString *someGlobalValue;

然后你有两个声明相同全局变量的编译单元,链接器将失败并出现重复的符号错误。如果你想拥有一个这样的变量,它在编译单元中只存在 ,并且对任何其他编译单元都是不可见的(即使它们使用extern),你可以使用{{ 1}}关键字:

static

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

答案 1 :(得分:2)

extern NSString * const MyConstant;

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

更可能的是,变量设置如下:

NSString * const MyConstant = @"foo";

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

答案 2 :(得分:-1)

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

Const表示设置后无法更改变量。但是,您可以使用一些指针误导,如下所示:

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

如果您需要(例如,在您的班级+initialize方法中),这实际上允许您更改它。