У каждой переменной есть класс хранения в C? - PullRequest
0 голосов
/ 12 февраля 2019

Наивно можно подумать, что это так, потому что обычно auto предполагается, когда ключевое слово класса хранения не указывается.

Тем не менее, для переменных в области файлов, помещающих перед ними auto,ошибка.

#include <stdio.h>

auto int x;

int main(void){
  x = 7;
  printf("x = %d", x);
}

Clang жалуется:

3:10: error: illegal storage class on file-scoped variable
auto int x;

Объявление x без какого-либо ключевого слова класса хранения, и оно компилируется:

#include <stdio.h>

int x;

int main(void){
  x = 7;
  printf("x = %d", x);
}

Теперь мне интересно, какое хранилищекласс x имеет в приведенном выше примере?У него есть имя?

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Есть ли у каждой переменной класс хранения в C?

Да, хотя в действительности для этого в стандарте используется термин "продолжительность хранения".Это то же самое, и стандарт также несколько непоследовательно использует термин «спецификатор класса хранения» для ключевых слов auto, static и т. Д.

Наивно можно подумать, что это так, потому чтообычно auto принимается, когда ключевое слово класса хранения не указано.

Нет.Точно нет.По умолчанию extern для функций и для всего, что объявлено в области видимости файла.Только идентификаторы для объектов, объявленных в области видимости блока, по умолчанию имеют значение auto.

Тем не менее, для переменных в области файлов, помещающих перед ними auto, выдает ошибку.

Как это должно.Стандарт прямо указывает, что

Спецификаторы класса хранения auto и register не должны появляться в спецификаторах объявления во внешнем объявлении.

[C11, пункт 6.9 / 2]

Объявление x без ключевого слова класса хранилища и компиляция [....]

Конечно.

Теперь мне интересно, что имеет класс хранения x в приведенном выше примере?У него есть имя?

Его класс хранения соответствует классу extern.Как я уже сказал, это значение по умолчанию для объявлений области файла.Но хотя стандарт использует терминологию «спецификатор класса хранения», опять же, он не использует «класс хранения» как отдельную концепцию.Он говорит вместо хранения длительность .Все переменные с внешними или внутренними связями имеют статическую длительность хранения, то есть они существуют на протяжении всей жизни программы.

0 голосов
/ 12 февраля 2019

Ключевые слова 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" является нарушением ограничения.Я не уверен, что он делает, если вы используете его в области видимости блока.

0 голосов
/ 12 февраля 2019

Из стандарта C § 6.2.4, пункт 3:

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

Выделение мое.Обратная ссылка § 6.2.2 параграф 5:

Если объявление идентификатора для функции не имеет спецификатора класса хранения, его связь определяется точно так, как если бы она была объявлена ​​с помощью спецификатора класса храненияехЬегп.Если объявление идентификатора для объекта имеет область действия файла и не имеет спецификатора класса хранения, его связь является внешней .

Снова выделите мое.

Итакглобальные переменные имеют статическую длительность хранения по умолчанию.Даже без стандарта, гарантирующего это, это единственный тип продолжительности хранения, который имеет смысл для глобальных переменных.

...