Ключевые слова auto
, static
, extern
, register
и _Thread_local
упоминаются в стандарте как спецификаторы класса хранения , но "объекты" (этоСтандартный термин для того, что мы обычно называем «переменными»), не имеет классов хранения.Вместо этого у них есть связь (внешняя, внутренняя, нет) и продолжительность хранения (статическая, автоматическая, нить).Кроме того, любое объявление объекта может быть или не быть определением.Спецификаторы класса хранения вместе с областью, в которой объект объявлен, и с наличием у него инициализатора (int foo
vs int foo = 3
), управляют этими свойствами.Проще всего показать, как это работает с таблицей:
sc-specifier scope initialized linkage storage duration is a definition
------------ ----- ----------- ------- ---------------- ---------------
auto file no [constraint violation]
auto file yes [constraint violation]
auto block no none automatic yes
auto block yes none automatic yes
none file no external static yes
none file yes external static yes
none block no none automatic yes
none block yes none automatic yes
static file no internal static yes
static file yes internal static yes
static block no none static yes
static block yes none static yes
extern file no external static no
extern file yes external static yes
extern block no external static no
extern block yes external static yes
Термин «спецификатор класса хранения» намеренно отличается от терминов «длительность хранения» и «связь», напоминая, что спецификаторы недать вам независимый контроль над продолжительностью хранения и связью.
Язык не дает вам независимого контроля над продолжительностью хранения, связью и определением, поскольку недоступные комбинации не имеют смысла.Длительность автоматического хранения имеет смысл только для переменных, объявленных в области видимости блока, а отсутствие определения имеет смысл только для переменных с внешней связью (поскольку только они могут быть определены в другом файле) и т. Д.
Я оставил register
и _Thread_local
вне таблицы, потому что они особенные.register
аналогично auto
, за исключением того, что оно также означает, что вам не разрешено брать адрес объекта._Thread_local
делает продолжительность хранения переменной "потоком" и не меняет связь;он может использоваться сам по себе или с extern
или static
, но объединение его с "auto" является нарушением ограничения.Я не уверен, что он делает, если вы используете его в области видимости блока.