Объем переменной вне основного в 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, которое может быть чем угодно. Другими словами, они дают вам память, полную любых данных (или частичных данных) в ней заранее.