7

请查看此标题:

// 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

并进入这个实现:

// 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

我有以下问题:

  1. 声明 (4) 和 (5) 或 (6) 和 (7) 之间有什么根本区别吗?
  2. “外部”声明(4)和包含在实现范围内的(6)之间有什么区别吗?
  3. 为什么在实现范围内声明的 (6) 和 (7) 可以在另一个实现范围 (9) 中访问?
  4. 为什么(2)在标头中声明可以访问(6)在实现范围内声明?
  5. 为什么 (1) 和 (3) 生成错误Cannot combine with previous 'extern' declaration specifier,但 (0) 和 (2) 编译时没有错误?
4

1 回答 1

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变量在另一个文件中声明的说法相冲突。

于 2012-07-08T11:03:00.237 回答