Objective-C中的静态变量声明如何不同?

Vad*_*dim 7 c cocoa global-variables objective-c static-variables

请查看此标题:

// Test.h
@interface Test : NSObject @end

extern id A;               // (0)
//extern static id B;      // (1) Uncomment to get a compiling error
extern id C;               // (2)
//extern static id D;      // (3) Uncomment to get a compiling error
Run Code Online (Sandbox Code Playgroud)

并进入这个实现:

// Test.m
#import "Test.h"

id A = @"A";               // (4)
static id B = @"B";        // (5)

@implementation Test

id C = @"C";               // (6)
static id D = @"D";        // (7)

@end

// Still Test.m

@interface Test2 : NSObject @end
@implementation Test2 : NSObject

+ (void)initialize {
    NSLog(@"%@ %@", A, B); // (8)
    NSLog(@"%@ %@", C, D); // (9)
}

@end
Run Code Online (Sandbox Code Playgroud)

我有以下问题:

  1. 声明(4)和(5)或(6)和(7)之间是否存在根本区别?
  2. "外部"声明(4)与实施范围(6)之间是否有任何区别?
  3. 为什么在实现范围内声明的(6)和(7)可以在另一个实现范围(9)中访问?
  4. 为什么(2)在header中声明可以访问(6)在实现范围内声明?
  5. 为什么(1)和(3)会产生错误Cannot combine with previous 'extern' declaration specifier,但是(0)和(2)编译时没有错误?

She*_* Lo 7

  1. 是,static在此上下文中使用将变量限制为文件的范围.

    如果你有(4)并id A = @"A"在项目的另一个文件中extern声明,即使没有标题中的声明,那么你将得到编译器错误.

    在(5)的情况下,如果您static id B = @"B"在另一个文件中声明,那么它将正常工作.

  2. 不,这些是C变量声明,不遵循Objective-C作用域规则.

  3. 由于Objective-C是C的超集,(6)和(7)只是简单的全局变量,就像它们在C中一样.

  4. (2)没有真正引用(6),它只是向其他文件声明#import它"信任我,有一个C在另一个文件中声明的变量",稍后在编译的目标文件被链接时解析.

  5. 如前所述static,将变量的范围限制为当前文件,因此它与extern另一个文件中声明的变量相冲突.