2012-01-12 3 views

ответ

3

ехЬегп

extern постоянная/переменная, которая одно определение может (или ссылки) через несколько объектных файлов. Это глобальный, экспортированный символ C. Используйте это, если вы хотите получить доступ к константной/глобальной переменной из нескольких единиц перевода (или скомпилированных файлов) или если вы хотите использовать его в нескольких двоичных файлах (например, вы хотите использовать его из своего приложения, а определение - в динамической библиотеке). Обычно вы объявляете это в заголовке для других пользователей.

статический

The static выдает копию для каждого перевода. Каждый файл, который скомпилирован, который также видит (например, #include d), статичный будет выдавать копию этого статического элемента. Вы должны избегать этого. Это приведет к раздутой бинарности, которая имеет очень запутанное выполнение. Вы должны одобрить статичность, если значение является локальным для файла и должно быть закрыто для этого файла.

По этим причинам вы должны поддержать static в ваших файлах .c, .m, .cpp и .mm и extern в ваших заголовках.

Наконец, что NSString указатель должен быть const по умолчанию:

// declaration - file.h 
extern NSString * const var1; 

// definition - file.m 
NSString * const var1 = @"var1"; 

или

static NSString * const var2 = @"var2"; 

Если вы все еще хотите больше, here's a related answer I wrote и here's another.

+1

Можно утверждать, что это тонкая точка, но квалификатор 'extern' сам не объявляет переменную глобальной видимостью (« linkage »выше) - глобальная переменная без' extern' имеет глобальную видимость. Однако, если вы решите относиться к нему так, как если бы вы, вероятно, не ошибетесь. Дальнейшие подробности в моем ответе. – CRD

+0

@CRD хорошая точка (+1), и хороший ответ (+1). мой ответ дает введение в тему. я избегал упоминания переменных без квалификации, потому что для них нет практического использования (ну, я предпочитаю явную квалификацию ...). – justin

+0

зависит от того, как вы определяете «практический». Хорошим шаблоном для глобалов является одно не-«внешнее» квалифицированное определение в файле кода, которое предоставляет глобальную и одну или несколько объявлений с «extern», которые ссылаются на глобальные. То есть эквивалентный шаблон для методов/функций - одно место определяет тело, одно или несколько мест ссылаются на метод/функцию с прототипом. В обоих случаях «один или несколько» часто означает только заголовок для файла кода, который определяет глобальную/метод/функцию. Теперь релаксация * позволяет * добавить 'extern' в def, но это не имеет смысла. – CRD

2

Глобальные переменные и static

Объявление переменной вне любого метода (и в Objective-C либо внутри, либо снаружи, @implementation/@end делает срок службы из переменной глобальной, которая является переменной будет существовать в течение всего периода времени, когда приложение выполняется.

глобальной переменной, без квалификации, или только с const и/или volatile классификаторов, является видимым откуда угодно. Так, например:

NSString *MyApplicationName; 

объявляет глобальную переменную MyApplicationName, которые могут быть доступны из любого места в приложении.

Видимость глобальной переменной (но не ее жизненного цикла) может быть ограничена только файлом (точнее «единиц компиляции», позволяющим использовать один файл, включая другие), содержащий объявление, путем присвоения ему static.Так, например:

static NSString *MyClassName; 

объявляет глобальную переменную MyClassName, которая видна только в текущем модуле компиляции.

Использование static квалифицированных глобальных деклараций в пределах @implementation/@end - это самое близкое, что Objective-C предлагает переменные класса «другие языки» других языков.

Вы не должны место глобальные переменные декларации, static квалификацию, или нет, в заголовочных файлах, которые приводят к нескольким различным декларациям - ошибка приведет, если нет static классификатор, а также несколько различных переменных с различными видимости областей если есть.

extern отборочные

extern отборочные делает что-то, а другое.

Первоначальное значение (небольшая релаксация теперь разрешено, смотри ниже), чтобы просто определить тип и имя глобальной переменной которая объявлена ​​в другом месте. То есть вы сообщаете компилятору: «существует глобальная переменная некоторого типа и имени, которое я хотел бы использовать, который будет предоставлен другой единицей компиляции». Например:

extern NSString *MyApplicationName; 

утверждает, что некоторые модули компиляции содержит декларацию (которая не должен быть static квалифицированы):

NSString *MyApplicationName; 

extern квалифицирована декларация сам по себе не вызывает выделение какого-либо хранилищ для глобального переменная.

Место extern квалифицированных деклараций в заголовочных файлах, это то, как единица компиляции рекламирует глобальные переменные, которые она хочет экспортировать. Вы также можете поместить их в файлы кода для ссылки на глобальные переменные, объявленные в другом месте. Внутри файла кода вы можете разместить квалифицированную декларацию extern вне любого метода/функции - в этом случае имя/тип доступно для всей единицы компиляции - или внутри метода/функции - и в этом случае видимость имени/тип ограничивается только этим методом/функцией.

Небольшой релаксация

Первоначально вы должны были иметь одну не- заявления extern квалификатора, чтобы удовлетворить любые extern квалифицированных из них. Однако это было позже изменено, если при объединении различных единиц компиляции ни одна из них не объявляет глобальную переменную, на которую ссылается некоторая extern квалифицированная декларация, тогда компоновщик (обычно?) Просто генерирует эту переменную и добавляет ее в результирующий двоичный файл, а не создает «Отсутствует глобальная» ошибка. Лучшая практика программирования заключается не в том, чтобы полагаться на это расслабление - всегда есть не-extern квалифицированное объявление для каждой глобальной переменной.

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