常量的解释

Jon*_*an. 4 constants objective-c

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

extern NSString * const MyConstant;
Run Code Online (Sandbox Code Playgroud)

有了这条线,究竟extern是什么意思,究竟是什么const意思?

Ada*_*gan 19

你在这里问了两个问题:一个关于常数,一个关于外部问题.这两者不一定相关.

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

NSString * const MyConstant = @"foo";
Run Code Online (Sandbox Code Playgroud)

你已经声明了一个指向非常量NSString对象的常量指针; 该const关键字是明星的权利,所以它指的是指针.因此,这个:

MyConstant = @"bar";
Run Code Online (Sandbox Code Playgroud)

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

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

const NSString *MyConstant = @"foo";
Run Code Online (Sandbox Code Playgroud)

还有这个:

NSString const *MyConstant = @"foo";
Run Code Online (Sandbox Code Playgroud)

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

const NSString * const MyConstant = @"foo";
Run Code Online (Sandbox Code Playgroud)

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

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

如果编译单元A在.m文件中声明全局:

#import "A.h"

NSString *someGlobalValue;
Run Code Online (Sandbox Code Playgroud)

和编译单元B想要使用全局:

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

@implementation B

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

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

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

NSString *someGlobalValue;
Run Code Online (Sandbox Code Playgroud)

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

static NSString * const someFileLevelConstant = @"wibble";
Run Code Online (Sandbox Code Playgroud)

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