静态内联函数调用之间静态变量的地址发生变化

时间:2014-06-13 11:50:43

标签: objective-c c

我不擅长C(我是iOS开发人员),所以这让我感到困惑:

我有一个头文件,我在其中定义了一些本地化助手:

#ifndef LocalizationMacros_h
#define LocalizationMacros_h

static NSString * forcedLanguage = nil;

static inline void forceLanguage(NSString*language){
    NSLog(@"Forcing language %@ (%i)", language, &forcedLanguage);
    // Output: Forcing language de (5248160)

    forcedLanguage = language;
}

static inline NSString * translate(NSString * language, NSString * key){
    NSLog(@"Forced language: %@ (%i)", forcedLanguage, &forcedLanguage);
    // Output: Forced language: (null) (5248236)

    // ... do some stuff to put translation into result ...
    return result;
}

#endif

我不明白为什么forcedLanguage的地址在forceLanguage()translate()之间发生变化,导致(null)作为其值。有人可以启发我吗?

2 个答案:

答案 0 :(得分:4)

您正在为包含标头的每个源文件定义forcedLanguage变量的副本。在标题更改中:

static NSString * forcedLanguage = nil;

为:

extern NSString * forcedLanguage;

然后在一个源文件(理想情况下与您的标题对应的文件)中定义:

NSString * forcedLanguage = nil;

为了将来参考,经验法则是:变量声明进入头文件,变量 definitions 进入源文件。

答案 1 :(得分:2)

static关键字将对象本地化到放置它的翻译单元 - 您已将其放在头文件中,因此它可以包含在多个翻译单元中。

这里static被用作连接修饰符;在这种情况下,它不是存储类说明符 - 在函数外部声明的所有数据在任何情况下都将具有静态存储类。你想要的是使它全球化(事实而不是推荐) - 即给它extern联系。无论您是否声明extern,外部链接都是默认值。

如果你给它外部链接,那么标题必须只包含一个声明,而不是实例化 - 实例化必须在一个翻译单元中。