Объем переменной вне основного в C

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

#include <stdio.h>

int x;

int main (void) 
{ }

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

Если это верно, то как оно отличается от extern?

Ответы

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

1)

static int x;

int main() { }

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

2)

int main() {
   static int x;
}

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

Ответ 7

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

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

extern int x;

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

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

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