Область действия переменной за пределами главной в C - PullRequest
14 голосов
/ 24 февраля 2011

Рассмотрим код:

#include <stdio.h>

int x;

int main (void) 
{ }

Значение x равно 0 внутри main. Но почему это так? Я не объявил, что это static. Или предполагается, что static вне функции?

Если приведенное выше верно, чем оно отличается от extern?

Ответы [ 7 ]

21 голосов
/ 24 февраля 2011

Это ни static, ни extern.Это переменная, видимая для модуля компиляции, в котором она находится, и дополнительно будет видна из всех модулей компиляции, которые объявляют x переменной extern.

Почему я говорю, что это не static и extern?

Если это был extern, тогда должна быть другая единица компиляции с объявлением x.Ясно, что это ваша единственная единица компиляции.

Если бы это было static, тогда никакая ссылка extern не была бы разрешена для переменной x, определенной в этой единице компиляции.Мы знаем, что мы могли бы легко объявить переменную extern для этого x, объявленного здесь.

Почему 0 присвоено x?Потому что в C все глобальные переменные инициализируются в 0.Об этом говорится в 6.7.8 (10) стандарта C99.

6 голосов
/ 24 февраля 2011

Когда мы говорим, что переменные «длительности статической памяти» неявно инициализируются равными 0, мы не имеем в виду, что перед ними нужно поставить ключевое слово «static».

«статическая длительность хранения» - это просто особый вид продолжительности хранения объектов, который говорит, что их хранение длится в течение всей продолжительности программы.Этот тип времени хранения используется для переменных, объявленных в области видимости файла (например, для вашей переменной), и локальных статических переменных.

4 голосов
/ 24 февраля 2011

6.2.2 / 5: «Если объявление идентификатора для объекта имеет область действия файла и не имеет спецификатора класса хранения, его связь является внешней.»

Это связь , но не scope . Ваше объявление x будет иметь область действия файла в любом случае. static и extern не влияют на область действия. Он инициализирован в 0, потому что x имеет статическую продолжительность хранения (см. 6.2.4 / 3 и /5).

В общем, вы также должны знать о 6.2.2./4:

Для идентификатора, объявленного с спецификатор класса хранения extern в объем, в котором предварительная декларация этот идентификатор виден, если предварительная декларация определяет внутренний или внешняя связь, связь идентификатор в более позднем объявлении так же, как связь, указанная в предыдущая декларация.

Таким образом, объявление с помощью extern не совсем то же самое, что объявление без спецификатора класса хранения. В вашем примере нет предварительного объявления.

2 голосов
/ 24 февраля 2011

Это не статично. Это глобально. Вы можете объявить его extern в другом модуле компиляции, но в этом будет выделено место для него. Между прочим, глобалы всегда инициализируются в 0, если им не даны инициализаторы.

1 голос
/ 24 февраля 2011

x - глобальная переменная, для нее выделено место при запуске программы, и она инициализируется значением 0 (как правило, однако у вас должен быть явный инициализатор).

Ключевое слово static имеет два разных значения.

1)

static int x;

int main() { }

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

2)

int main() {
   static int x;
}

Это фактически превращает x в глобальную переменную. Хотя область действия все еще находится в главной функции, для нее выделено пространство глобально, и ее значение будет сохраняться между вызовами main ().

1 голос
/ 24 февраля 2011

Ваш компилятор инициализировал значение x равным 0.

Это глобальная переменная, которая видна из main()

0 голосов
/ 24 февраля 2011

Это похоже на домашнее задание, но я все равно укушу.

Чтобы использовать x, который вы определили здесь в классе или функции из другого файла, вы должны использовать

extern int x;

Если вы используете переменную x (как в заголовке), вы можете использовать x так же, как в main ().extern сообщает компилятору, что вы используете переменную, которая определена / создана в другом месте.

Если вы хотите, чтобы она существовала до запуска main, то вы используете static, который обрабатывается до запуска main ().Другими словами, он загружает пространство памяти с переменными до начала какой-либо обработки (в основном).

Что касается того, почему при запуске он равен 0, то, скорее всего, ваш компилятор присваивает ему базовое значение.Не все компиляторы делают это, если я не ошибаюсь, многие просто дадут вам то, что было в пространстве памяти, выделенном для x, которое может быть чем угодно.Другими словами, они дают вам память, заполненную теми данными (или частичными данными), которые были в ней заранее.

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