Когда происходит инициализация глобальных переменных? - PullRequest
2 голосов
/ 03 января 2012

Я знаю, когда программа запускается, функция main () выполняется первой. Но когда происходит инициализация глобальных переменных, объявленных вне main ()? Я имею в виду, если я объявлю переменную следующим образом:

unsigned long current_time = millis();

void main() {
    while () {
        //some code using the current_time global variable 
    }
}

Здесь важно точное время инициализации глобальной переменной. Пожалуйста, расскажите, что происходит в этом контексте.

Ответы [ 2 ]

3 голосов
/ 03 января 2012

Поскольку вы не определили язык, о котором говорите, я предположил, что это C ++.

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


В принципе, переменная, определенная вне любой функции (то есть, глобальные, пространство имен и статические переменные класса), инициализируется перед main () вызывается.Такие нелокальные переменные в единице перевода инициализируются в порядке их объявления (§10.4.9).Если такая переменная не имеет явного инициализатора, она по умолчанию инициализируется для ее типа по умолчанию (§10.4.2).Значение инициализатора по умолчанию для встроенных типов и перечислений равно 0. [...] Не существует гарантированного порядка инициализации глобальных переменных в разных единицах перевода.Следовательно, неразумно создавать зависимости порядка между инициализаторами глобальных переменных в разных единицах компиляции.Кроме того, невозможно поймать исключение, выданное инициализатором глобальной переменной (§14.7).Как правило, лучше всего минимизировать использование глобальных переменных и, в частности, ограничить использование глобальных переменных, требующих сложной инициализации. См. .

2 голосов
/ 13 января 2012

(Быстрый ответ: стандарт C не поддерживает этот тип инициализации; вам придется ознакомиться с документацией вашего компилятора.)

Теперь, когда мы знаем, что язык C, мы можем видеть, что говорит стандарт об этом.

C99 6.7.8, пункт 4:

Все выражения в инициализаторе для объекта, который имеет статический продолжительность хранения должна быть константными выражениями или строковыми литералами.

И новый стандарт 2011 года (по крайней мере, проект, который я имею) гласит:

Все выражения в инициализаторе для объекта, который имеет статический продолжительность хранения должна быть константными выражениями или строковыми литералами.

Таким образом, инициализация статического объекта (например, глобального, такого как ваш current_time) с помощью вызова функции является нарушением ограничения. Компилятор может отклонить его или может принять его с предупреждением и делать все, что ему нравится, если он обеспечивает расширение языка.

Стандарт C не говорит, когда происходит инициализация, потому что он не допускает такого рода инициализацию. По сути, ни один из ваших кодов не может быть выполнен до начала выполнения функции main().

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

(Обычно main объявляется как int main(void) или int main(int argc, char *argv[]) или эквивалентный, или некоторым образом, определяемым реализацией. Во многих случаях void main() указывает программиста, который изучил C из плохо написанной книги, из их слишком много. Но это относится только к размещенным реализациям. Отдельно стоящие реализации, обычно для встроенных систем, могут определять точку входа в программу любым удобным для них способом. Поскольку вы ориентируетесь на Arduino, вы, вероятно, используете автономную реализацию, и Вы должны объявить main(), однако, документация компилятора говорит вам.)

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