2011-02-24 2 views
13

Рассмотрим код:Объем переменной за пределами главной в C

#include <stdio.h> 

int x; 

int main (void) 
{ } 

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

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

+0

Вы можете уточнить свой вопрос о 'extern'? –

+0

Если я хочу объявить внешнюю переменную, не так ли получается? – Kanishk

+0

Разница между этим и внешним заключается в том, что внешний интерфейс является внешним, и это не так. –

ответ

19

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

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

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

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

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

+0

А, я вижу. Итак, почему инициализируется 0? – Kanishk

+0

@ Kanishk: рассмотрите функцию, в которой завершается * файл *, над которым вы работаете. Это область применения этой декларации. Область «extern» охватывает несколько файлов. – Eelvex

+0

@ Kanishk: немного обновил свой ответ. @Eelvex: спасибо за разъяснение, что ... –

1

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

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

+0

Но когда я хочу, чтобы это была внешняя переменная, я делаю то же самое. Так в чем же разница? – Kanishk

+0

Я не следую вашему вопросу? Что вы ожидаете от того, что не видите? –

+0

Ответ Пабло позаботится об этой части. – Kanishk

2

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

+0

Поэтому, когда я называю это другим компиляционным модулем с использованием ключевого слова 'extern', он делает его внешней переменной, но для этого файла он глобальный. Правильно? – Kanishk

+0

@ Kanishk: Это глобально в обоих файлах, просто объявление 'extern' для него в другом файле не вызывает выделения какого-либо пространства. Он получает адрес от компоновщика, который получает адрес из этого файла. – nmichaels

+0

Ааа! Благодарю. Я получаю это сейчас. – Kanishk

5

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

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

+2

Ах, многие значения «статические». –

+2

контекстно-зависимые ключевые слова ...... –

3

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

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

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

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

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

+0

Стандарт - святой Грааль, в другом вопросе, который я задавал раньше, люди цитировали стандарт. Спасибо, хотя :-) – Kanishk

+0

@ Канишк: цитирование стандарта - это непрерывный процесс. Чем больше вы ссылаетесь на него, тем больше его стиль и жаргон начинают иметь смысл. Тогда вы можете уклониться от примеров из учебников, полузабытых правил и инстинкта кишки :-) –

1

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

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

1)

static int x; 

int main() { } 

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

2)

int main() { 
    static int x; 
} 

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

0

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

Для использования х вы определили здесь в классе или функции из другого файла, вы должны использовать

extern int x; 

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

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

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

+2

Как это домашнее задание? Я не прошу написать код для меня. Я спрашиваю то, что я пробовал. Домашние вопросы не такие. – Kanishk

Смежные вопросы