Обратите внимание, что внешняя переменная, определенная в одном файле, не будет доступна во втором файле до тех пор, пока ее также там не объявить (с использованием extern). Само по себе внешнее объявление лишь делает переменную потенциально доступной другим файлам.
Однако исторически сложилось так, что многие компиляторы в этом отношении следуют другим правилам. Например, многие системы Unix позволяют объявлять переменную в нескольких файлах без указания ключевого слова extern при условии, что только одно объявление включает инициализацию. Объявление с инициализацией считается определением.
498 глава 12
Спецификаторы классов хранения
Вы могли уже заметить, что смысл ключевых слов static и extern зависит от контекста. В языке С имеется шесть ключевых слов, которые сгруппированы вместе как спецификаторы классов хранения: auto, register, static, extern, _Thread_local и typedef. Ключевое слово typedef ничего не говорит о хранении в памяти, но оно нрисугствует здесь по синтаксическим причинам. Например, в большинстве случаев вы можете использовать в объявлении не более одного спецификатора класса хранения, а это означает, что вы не можете применять один из спецификаторов класса хранения в качестве части typedef. Исключением является спецификатор _Thread_ local, который можно использовать вместе со спецификаторами static и extern.
Спецификатор auto указывает переменную с автоматической продолжительностью хранения. Он может применяться только в объявлениях переменных с областью видимости в пределах блока, которые уже имеют автоматическую продолжительность хранения, так что главным его предназначением является документирование.
Спецификатор register также может использоваться только с переменными, имеющими область видимости в пределах блока. Он помещает переменную в регистровый класс хранения, что равносильно запросу на минимизацию времени доступа к ней. Он также предотвращает взятие адреса этой переменной.
Спецификатор static создает объект со статической продолжительностью хранения, который появляется после загрузки программы в память и исчезает при завершении программы. Если static применяется в объявлении с областью видимости в пределах файла, то область видимости ограничивается одним этим файлом. Если static используется в объявлении с областью видимости в пределах блока, то область видимости ограничивается этим блоком. Таким образом, объект существует и сохраняет свое значение на протяжении выполнения программы, но может быть доступен посредством идентификатора, только когда выполняется код внутри его блока. Статическая переменная с областью видимости в пределах блока не имеет связывания. Статическая переменная с областью видимости в пределах файла имеет внутреннее связывание.
Спецификатор extern указывает, что вы объявляете переменную, которая была определена в каком-то другом месте. Если объявление, содержащее extern, имеет область видимости в пределах файла, то переменная, на которую производится ссылка, должна иметь внешнее связывание. Если объявление с extern имеет область видимости в пределах блока, то ссылаемая переменная может иметь либо внешнее, либо внутреннее связывание, что зависит от определяющего объявления этой переменной.
Сводка; классы хранения
Автоматические переменные имеют область видимости в пределах блока, не имеют связывания и характеризуются автоматической продолжительностью хранения. Эти переменные локальны и закрыты для блока (обычно функции), в котором они определены. Регистровые переменные обладают такими же свойствами, как автоматические переменные, но для их хранения компилятор может применять более быструю память или регистры. Адрес регистровой переменной получать нельзя.
Переменные со статической продолжительностью хранения могут иметь внешнее связывание, внутреннее связывание или вообще не иметь связывания. Когда переменная объявляется внешней по отношению к любой функции в файле, то она представляет собой внешнюю переменную и имеет область видимости в пределах файла, внешнее связывание и статическую продолжительность хранения.
Классы хранения, связывание и управление памятью 499
Если вы добавите к такому объявлению ключевое слово static, то получите переменную со статической продолжительностью хранения, областью видимости в пределах файла и внутренним связыванием. Если вы объявляете переменную внутри функции и указываете ключевое слово static, то данная переменная получает статическую продолжительность хранения, область видимости в пределах блока и отсутствие связывания.
Читать дальше