2013-08-06 2 views
2

Я вижу что-то странное, когда я запускаю код, который использует ключевое слово 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); 

} 

Когда я использую Экстерн ключевое слово в моих методах, код работает правильно и приводит к целому числу 3 печати. Однако, когда я удаляю extern, целое число 2 печатается. Почему это? Поскольку gCounter - статическая переменная, не должно ли это работать без ключевого слова extern?

+1

Когда вы удаляете extern, удаляете ли вы всю декларацию или вы оставляете ее как 'int gCounter'? –

+0

@HotLicks Я оставляю его как int gCounter. – Brosef

+0

Избавьтесь от всех строк 'extern in gCounter;'. Вы не хотите их, если ваша цель - ссылаться на статический 'gCounter'. – rmaddy

ответ

3

Вы должны понимать разницу между declaration и definition:

  • static int x и int x являются определения. Компилятор резервирует память для x.
  • extern int x С другой стороны, это декларация. Вы говорите компилятору, что существует переменная x, которая определена где-то в другом месте.

Кроме того, вы можете определить различные переменные в различных областях, которые имеют то же имя переменной:

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

Так что, если вы пишете

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

вы приращением функции локального x.

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

Смежные вопросы