Справочное руководство по C++

R.7.1.1 Спецификации класса памяти.

Спецификации класса памяти могут быть такие:

Спецификация-класса-памяти:

 auto.

 register.

 static.

 extern.

Спецификации auto и register могут применяться только для имен объектов, которые описаны в блоке (§R.6.3), или для формальных параметров (§R.8.3). Почти всегда спецификация auto избыточна и используется не часто, так, auto используется, чтобы явно отделить оператор-описание от оператора-выражения (§R.6.2).

Описание register является описанием auto, которое подсказывает транслятору, что описываемые переменные будут использоваться достаточно интенсивно. Подсказка может быть проигнорирована, и во многих реализациях она игнорируется в том случае, когда берется адрес переменной.

Описание объекта считается определением, если только оно не содержит спецификации extern и инициализации (§R.3.1).

Определение приводит к выделению памяти соответствующего размера и выполнению соответствующей инициализации (§R.8.4).

Спецификации static и extern могут применяться только к именам объектов или функций или к анонимным объединениям. Внутри блока недопустимы описания функций со спецификацией static или формальных параметров со спецификацией static или extern. Статические члены класса описываются в §R.9.4. Спецификация extern недопустима для членов класса.

Имя со спецификацией static подлежит внутреннему связыванию. Объекты, описанные как const, подлежат внутреннему связыванию, если только они не были описаны с внешней связью. Имя со спецификацией extern подлежит внешнему связыванию, если только ранее оно не было описано с внутренней связью. Имя с файловой областью видимости и без спецификации-класса-памяти подлежит внешнему связыванию, если только ранее оно не было описано с внутренней связью или со спецификацией const. В смысле связывания для функций, не являющихся членами, спецификация inline эквивалентна static (§R.3.3). Для одного имени все его спецификации, определяющие связывание, должны быть согласованы. Например,

Static char* f(); // f() имеет внутреннее связывание.

Char* f() // f() все еще внутреннее.

{/*… */}.

Char* g(); // g() имеет внешнее связывание.

Static char* g() // ошибка: противоречие в связывании.

{/*… */}.

Static int a; // `a' имеет внутреннее связывание.

Int a; // ошибка: второе определение.

Static int b; // `b' имеет внутреннее связывание.

Extern int b; // `b' все еще внутреннее.

Int c; // `c' имеет внешнее связывание.

Static int c; // ошибка: противоречие в связывании.

Extern int d; // `d' имеет внешнее связывание.

Static int d; // ошибка: противоречие в связывании.

Имя неопределенного класса можно использовать в описании extern. Однако, такое описание нельзя использовать прежде, чем класс будет определен, например,

Struct S;

Extern S a;

Extern S f();

Extern void g(S);

Void h().

{

 g(a); // ошибка: S неопределено.

 f(); // ошибка: S неопределено.

}