使用extern获得静态变量

使用extern获得静态变量

问题描述:

当我运行一些使用extern关键字引用实现文件中的静态变量的代码时,我看到了一些奇怪的东西。所以我在我的实现文件中声明了静态变量gCounter,并在同一个实现文件中的两个方法中引用它(因为它的静态方法)。但是,当我在我的方法中使用extern关键字时,我得到了不同的结果。我的理解(从阅读我的书)是,当您引用与您的方法相同的文件中声明的静态变量时,extern不是必需的。代码如下:使用extern获得静态变量

/**接口**/

#import <Foundation/Foundation.h> 

@interface Fraction : NSObject 

+(Fraction *) allocF; 
+(int) count; 

@end 

/**implementation**/ 

#import "Fraction.h" 

static int gCounter; 

@implementation Fraction 

+(Fraction *) allocF 
{ 
    extern int gCounter; 
    ++gCounter; 

    return [Fraction alloc]; 
} 

+(int)count 
{ 
    extern int gCounter; 
    return gCounter; 

} 

@end 

/**main**/ 
#import "Fraction.h" 

int main (int argc, const char * argv[]) 
{ 

    @autoreleasepool 
    { 

    Fraction *a, *b, *c; 

    NSLog(@"The number of fractions allocated: %i", [Fraction count]); 

    a = [[Fraction allocF] init]; 

    b = [[Fraction allocF] init]; 

    c = [[Fraction allocF] init]; 


    NSLog(@"The number of fractions allocated: %i", [Fraction count]); 

    } 

    return(0); 

} 

当我使用extern关键字在我的方法中,所述代码工作正常,并且导致整数3进行打印。但是,当我删除extern时,整数2被打印。这是为什么?由于gCounter是一个静态变量,这不应该没有extern关键字?

+1

当你删除extern时,你是否删除了整个声明,还是把它作为'int gCounter'? –

+0

@HotLicks我把它作为int gCounter。 – Brosef

+0

摆脱gCounter;'行中的整个'extern。如果你的目标是引用静态的'gCounter',你不需要它们。 – rmaddy

您需要了解declarationdefinition之间的区别:

  • static int xint x的定义。编译器为x保留内存。
  • extern int x另一方面是一个声明。你告诉编译器,在其他地方定义了一个变量x。如果你写

    int x; 
    void foo() { 
        int x; 
        x++; 
    } 
    

    你是递增函数的局部x

    int x = 0; 
    { 
        int x = 1; 
        NSLog(@"x = %d", x); // x = 1 
    } 
    NSLog(@"x = %d", x); // x = 0 
    

    所以:

此外,您还可以定义不同的范围不同的变量,即具有相同的变量名。

int x; 
void foo() { 
    x++; 
} 

增加全球x

int x; 
void foo() { 
    extern int x; 
    x++; 
} 

您需要声明extern int x如果您的x定义是在另一个编译单元,如果是在同一个编译单元,最后两个是等价的。

+0

感谢您的例子。我使用了本书中的同一个例子。在这个例子之后,这本书说:“回想一下,在两个方法中不需要extern声明,因为gCounter变量是在文件中定义的。”那是怎么回事? – Brosef

+0

'extern'声明一个变量,该变量在不同的编译单元中定义(例如一个不同的.m文件)。如果你定义一个全局变量并在同一个文件中使用它,编译器会发现它是定义。 – Sebastian