|
|
Спецификации класса памяти могут быть такие:
спецификация-класса-памяти:
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 неопределено }
| |