Почему я не могу инициализировать статическую переменную с нелитературным значением?

У меня был этот код:

int foo(void){
 return 1;
}
int main(void){
 static const int x = foo();
 //do stuff
 return 0;
}

Но у меня возникла ошибка в инициализации статической переменной с неконстантным значением. Я думал, что это как-то связано со спецификатором const, но это не так. Я закончил сбрасывать ключевое слово const и делаю следующее:

int foo(void){
 return 1;
}
int main(void){
 static int x = 0;
 if (x == 0) x = foo();
 //do stuff
 return 0;
}

Теперь, почему компилятор не может просто задержать инициализацию переменной static int x до тех пор, пока она не будет использована, и что еще более важно, почему он не может просто поместить ее в раздел "чтение-запись" и просто принудить ее написано во время компиляции? Я хотел бы использовать ключевое слово const И static для улучшения семантики в моем коде, но мне все равно, как компилятор справляется с этим, просто дайте ему работать.

Неужели мое понимание стандарта C неверно? Или мой компилятор сосать? Это MSVC 9.0.

3 ответа

C требует этого.

Из стандарта C:

(C99, 6.7.8p4) "Все выражения в инициализаторе для объекта с длительностью статического хранения должны быть постоянными выражениями или строковыми литералами".

Обратите внимание, что определитель const не означает константу, а скорее только для чтения. Объект const не является константой в C.

Причина, по которой статический объект не может быть инициализирован не постоянным значением, связан с тем, что инициализация статического объекта выполняется "до запуска программы" (C99, 6.2.4p3).


Это ограничение происходит из стандартного раздела C. 6.7.8/4, поэтому он не только ваш компилятор:

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

Причиной этого является то, что, в отличие от стандарта С++, C не требует, чтобы среды исполнения предоставляли точку входа для инициализации перед запуском (в то время как, конечно, не запрещая ее). Способ и время статической инициализации (5.1.2) неуточнены).


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

licensed under cc by-sa 3.0 with attribution.