Адрес статической константы не является постоянным выражением?

#c #static #constant-expression

#c #статический #constant-expression

Вопрос:

Я думал, что address-of-static был постоянным выражением, как в примере ниже, но я получаю ошибку компилятора (или это новое для C 0x?)

 class X {
    static const int x;
    enum { y = amp;x };
};
  

Ответ №1:

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

На самом деле, GCC выдает очень четкое сообщение об ошибке:

prog.cpp:7: ошибка: ‘X::x’ не может появиться в постоянном выражении
prog.cpp:7: ошибка: `amp;’ не может появиться в постоянном выражении

Посмотрите сами : http://ideone.com/FJk3C


Однако допускается следующее:

 class X {
    static const int x;
    enum { y = sizeof(x) }; //okay. sizeof(x) can be known at compile time!
};
  

Не путайте константы времени компиляции с константами времени выполнения. Это две разные вещи.

Комментарии:

1. $ 5.19.2 в open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf кажется, это противоречит.

2. @Helltone: Это не противоречит этому. Константы времени компиляции и константы времени выполнения — это две разные вещи.

3. Читайте дальше в 5.19 (2). Одной из запрещенных вещей является «преобразование типа из типа указателя или типа указателя на член в литеральный тип». 3.9(10) определяет «литеральный тип» как включающий «скалярный тип», а «скалярные типы» включают «арифметические типы».

Ответ №2:

Читаем стандарт 1998 года, 5.19(1): «В нескольких местах C требует выражений, которые преобразуются в целое число или перечисление constant…as инициализаторы перечислителя (7.2) ….»

Далее, «целочисленное константное выражение может включать только….В частности, за исключением sizeof выражений, не должны использоваться функции, объекты класса, указатели или ссылки ….»

Плавающие литералы явно перечислены как приводимые к целому типу или типу перечисления, и больше ничего.

Приведение даже выражения-константы адреса для создания инициализатора перечислителя было недопустимым с первого стандарта.

Ответ №3:

Это постоянное выражение, но его нельзя определить во время компиляции. Фактическое значение адреса будет зависеть от области памяти, в которую исполняемый файл в конечном итоге загружается любым загрузчиком ОС, выполняющим эту функцию. Члены Enum должны иметь значения, которые могут быть определены компилятором.

Приветствую,
Дж.

Ответ №4:

Адрес статического объекта является постоянным выражением, но это не целочисленное постоянное выражение, поскольку оно не имеет целочисленного типа. И reinterpret_cast приведение его к целочисленному типу все еще не делает его целочисленным постоянным выражением, поскольку reinterpret_cast это недопустимо в целочисленных постоянных выражениях. А инициализатору enum значения требуется целочисленное постоянное выражение.

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

Ответ №5:

Программа неправильно сформирована, потому что:

  • адрес объекта не является целым постоянным выражением
  • для получения адреса x требуется определение (n вне класса)
  • использование интегрального элемента static const в любом месте, за исключением случаев, когда требуется интегральное выражение-константа, требует определения.