这两个代码块是否相同?我基本上要问的是,如果我在案例1中将extern关键字从globalVariable中删除,它是否仍然具有外部访问权限?唯一的区别是当你离开extern关键字时,你可以初始化变量吗?
int globalVariable = 1;
@interface Square : Rectangle
-(instancetype) initWithSide: (int) s;
-(void) setSide: (int) s;
-(int) side;
@end
extern int globalVariable;
@interface Square : Rectangle
-(instancetype) initWithSide: (int) s;
-(void) setSide: (int) s;
-(int) side;
@end
答案 0 :(得分:2)
不,这些不一样。
如果这是一个全局版,您将在.h
中引用,则可以使用extern
引用。如果您在没有.h
关键字的extern
中声明此全局,但是从多个.h
文件中包含此.m
,那么您最终会发出有关重复的警告符号,如:
duplicate symbol _globalVariable in:
/Users/.../Library/Developer/Xcode/DerivedData/...-eplmsbsfhnuvekewnlgooclttbpr/Build/Intermediates/....build/Debug-iphonesimulator/....build/Objects-normal/x86_64/ViewController.o
/Users/.../Library/Developer/Xcode/DerivedData/...-eplmsbsfhnuvekewnlgooclttbpr/Build/Intermediates/....build/Debug-iphonesimulator/....build/Objects-normal/x86_64/AppDelegate.o
duplicate symbol _globalVariable in:
/Users/.../Library/Developer/Xcode/DerivedData/...-eplmsbsfhnuvekewnlgooclttbpr/Build/Intermediates/....build/Debug-iphonesimulator/....build/Objects-normal/x86_64/ViewController.o
/Users/.../Library/Developer/Xcode/DerivedData/...-eplmsbsfhnuvekewnlgooclttbpr/Build/Intermediates/....build/Debug-iphonesimulator/....build/Objects-normal/x86_64/main.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
因此,正确的方法是将extern
放在.h
文件中(因此包含此标头的任何.m
文件都可以看到全局):
extern int globalVariable;
然后只初始化一次,在.m
文件中执行此操作,该文件对应于您声明它的.h
文件:
int globalVariable = 1;
显然,如果您打算仅使用一个.m
文件中的全局,那么您可以在一个.m
文件中定义它(但通常使用static
来确保它范围有限):
static int globalVariable = 1;
答案 1 :(得分:0)
int foo;
是“常用”符号的声明。
int foo = 1;
是符号的定义(带有外部链接)。
extern int foo;
是外部符号的声明。
通常,应避免使用常用符号。
据我所知,如果链接器找到了常见的符号引用但没有定义它,那么它将使一个没有警告。
相比之下,必须有一个定义才能满足对外部符号的引用。
为了更加清晰,我将引用the GNU ld
manual's explanation of its --warn-common
option:
--warn-common
当公共符号与另一个公共符号或符号定义组合时发出警告。 Unix连接器允许这有点草率 实践,但其他一些操作系统上的链接器没有。这个 选项允许您通过组合全局来发现潜在的问题 符号。不幸的是,一些C库使用这种做法,所以你可以 得到一些关于图书馆和你的符号的警告 程序有三种全局符号,这里用C示例说明:
int i = 1;
定义,位于输出文件的初始化数据部分。
extern int i;
未定义的引用,不分配空间。变量必须有定义或公共符号 某处。
int i;
一个共同的象征。如果变量只有(一个或多个)公共符号,则它会进入未初始化的数据区域 输出文件。链接器合并多个公共符号 变量为单个符号。如果它们的大小不同,那就是它 选择最大的尺寸。链接器将公共符号转换为a 声明,如果有相同变量的定义。
--warn-common
选项可以产生五种警告。每个警告由一对线组成:第一个描述了 刚刚遇到的符号,第二个描述了前一个符号 遇到同名的。两个符号中的一个或两个将是 一个共同的符号。
将公共符号转换为引用,因为已经有符号的定义。
file(section): warning: common of `symbol' overridden by definition file(section): warning: defined here
将公共符号转换为引用,因为会遇到符号的后续定义。这和 之前的情况,除了符号遇到不同的情况 顺序。
file(section): warning: definition of `symbol' overriding common file(section): warning: common is here
将公共符号与之前相同大小的公共符号合并。
file(section): warning: multiple common of `symbol' file(section): warning: previous common is here
将公共符号与之前较大的公共符号合并。
file(section): warning: common of `symbol' overridden by larger common file(section): warning: larger common is here
- 醇>
将公共符号与先前较小的公共符号合并。除了符号之外,这与前一种情况相同 以不同的顺序遇到。
file(section): warning: common of `symbol' overriding smaller common file(section): warning: smaller common is here