#objective-c #c
#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, amp;forcedLanguage);
// Output: Forcing language de (5248160)
forcedLanguage = language;
}
static inline NSString * translate(NSString * language, NSString * key){
NSLog(@"Forced language: %@ (%i)", forcedLanguage, amp;forcedLanguage);
// Output: Forced language: (null) (5248236)
// ... do some stuff to put translation into result ...
return resu<
}
#endif
Я не понимаю, почему адрес forcedLanguage
изменяется между forceLanguage()
и translate()
, что приводит к (null)
его значению. Может кто-нибудь просветить меня?
Комментарии:
1. Я предполагаю, что
inline
это приводит к созданию отдельного статического файла, локального для каждой единицы компиляции. Находятся ли ваши два метода в разных единицах компиляции?
Ответ №1:
Вы определяете копию forcedLanguage
переменной для каждого исходного файла, который включает ваш заголовок. В вашем изменении заголовка:
static NSString * forcedLanguage = nil;
Для:
extern NSString * forcedLanguage;
а затем в одном исходном файле (в идеале в том, который соответствует вашему заголовку) определите:
NSString * forcedLanguage = nil;
Для дальнейшего использования, эмпирическое правило таково: объявления переменных хранятся в заголовочных файлах, определения переменных — в исходных файлах.
Ответ №2:
static
Ключевое слово локализует объект в единицу перевода, в которую он помещен — вы поместили его в заголовочный файл, поэтому его можно включить в несколько единиц перевода.
Здесь static
используется как модификатор связи; в данном контексте это не спецификатор класса хранения — все данные, объявленные вне функции, в любом случае будут иметь статический класс хранения. Здесь вы хотите сделать его глобальным (фактически, а не рекомендацией), т. Е. Дать ему extern
связь. Внешняя связь используется по умолчанию, независимо от того, объявляете вы ее extern
или нет.
Если вы предоставляете ему внешнюю связь, то заголовок должен содержать только объявление, а не экземпляр — экземпляр должен быть в одной единице перевода.
Комментарии:
1. Вы имеете в виду «единицу компиляции» (в отличие от «единицы перевода»)? Я думаю, что приму этот ответ, хотя оба хороши, потому что это объясняет, почему немного больше.
2. единица компиляции / единица преобразования — это одно и то же. en.wikipedia.org/wiki/Translation_unit_ (программирование)