Почему я получаю сообщение об ошибке, что инициализатор не является константой?

Я использую следующий код.

const int X_ORIGIN = 1233086;             
const int Y_ORIGIN = -4728071;              
const int Z_ORIGIN = 4085704;
const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

Когда я его компилирую, GCC выдает следующую ошибку.

Transformations.h:16:1: ошибка: элемент инициализатора не является константой

Что это значит? Как я могу исправить свой код?


person CodeKingPlusPlus    schedule 18.07.2012    source источник
comment
Почему бы не создать структуру, содержащую три позиции, а не массив? Выглядит немного нелогично...   -  person Nathan White    schedule 18.07.2012
comment
Следствием того, что сказал @nathanwhite, Джон Кармак сказал:   -  person Michael Buen    schedule 18.07.2012


Ответы (6)


Вы не можете сделать это в глобальном масштабе в C, только в локальном масштабе, т.е. внутри функции:

#define NUM_DIMENSIONS 3

const int X_ORIGIN = 1233086;             
const int Y_ORIGIN = -4728071;              
const int Z_ORIGIN = 4085704;

const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; // FAIL

void foo(void)
{
    const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN}; // OK
}

В качестве альтернативы вы можете скомпилировать код как C++, а не C.

person Paul R    schedule 18.07.2012
comment
Это определение, а не const int важно. По-видимому, проклятый размер не может быть какой-либо переменной (даже константой). - person MrMesees; 02.07.2017
comment
Только для класса автоматического хранения, т.е. внутри функции а не статического (или C11 _Thread_local). - person dave_thompson_085; 05.08.2017

Часто людей вводит в заблуждение название ключевого слова const, подразумевающее что-то вроде постоянного значения, которое нельзя изменить. По крайней мере, в C это означает только для чтения. const квалифицированные объекты в области файла не имеют надлежащей константности, чтобы служить инициализаторами массива.

В качестве примера непостоянной константы вполне нормально объявить

 const volatile unsigned int milliseconds_since_boot;

являющееся значением, которое обновляется вне контроля компилятора (например, регистр HW) и которое вам не разрешено назначать, т.е. оно доступно только для чтения.

person Jens    schedule 18.07.2012
comment
Почему минус? Если есть проблема, пожалуйста, дайте мне возможность исправить. - person Jens; 18.07.2012
comment
Не мой DV, но вы могли бы немного подробнее остановиться на реальной проблеме ОП. Этот пример трудно понять новичкам, которые могут даже не знать, что такое аппаратный регистр. - person too honest for this site; 12.09.2016

Я не настоящий программист;), но я бы сделал так:

#define X_ORIGIN (1233086)
#define Y_ORIGIN (-4728071)
#define Z_ORIGIN (4085704)
const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

Таким образом, это просто замена текста. Если компилятор все еще выдает пустышку, по крайней мере, вы на шаг ближе к пониманию, в чем проблема.

person John U    schedule 18.07.2012
comment
@nathanwhite Хотите уточнить? Макросы решают проблему просто отлично! (Предполагая, что NUM_DIMENSIONS где-то определено). - person Jens; 18.07.2012
comment
@nathanwhite Именно по этой причине элемент инициализатора не является постоянной ошибкой (ошибками). Наличие NUM_DIMENSIONS в качестве переменной (константной или нет) приводит к изменяющемуся изменению »xyzOrigin« в области файла. - person Daniel Fischer; 18.07.2012
comment
Еще лучше было бы полностью удалить NUM_DIMENSIONS и позволить размеру массива соответствовать количеству предоставленных элементов. - person Leushenko; 07.06.2013

В качестве альтернативы это также будет работать в этом случае:

enum { X_ORIGIN = 1233086,
       Y_ORIGIN = -4728071,
       Z_ORIGIN = 4085704 };

const int xyzOrigin[] = { X_ORIGIN, Y_ORIGIN, Z_ORIGIN };

int main()
{
    return 0;
}
person hmjd    schedule 18.07.2012

В языке C объекты со статической продолжительностью хранения должны быть инициализированы константными выражениями или агрегатными инициализаторами, содержащими константные выражения. --Ответ Андрея Т

После прочтения Вы должны знать, что NUM_DIMENSIONS, если оно имеет const-квалификацию, не является константой! Тогда вы не можете инициализировать свой массив таким образом.

Для использования этого кода:

const int xyzOrigin[NUM_DIMENSIONS] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

Вы должны использовать: #define NUM_DIMENSIONS 3 или вы можете просто объявить без какой-либо переменной внутри квадратных скобок const int xyzOrigin[] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};

person waldyr.ar    schedule 18.07.2012

Как сказал триклозан:

main()
{
    const int X_ORIGIN = 1233086;
    const int Y_ORIGIN = -4728071;
    const int Z_ORIGIN = 4085704;
    const int xyzOrigin[] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};
}

это работает нормально...

или, если вы знаете размеры заранее, это:

#define DIM 3

main()
{
    const int X_ORIGIN = 1233086;
    const int Y_ORIGIN = -4728071;
    const int Z_ORIGIN = 4085704;
    const int xyzOrigin[DIM] = {X_ORIGIN, Y_ORIGIN, Z_ORIGIN};
}
person Bruno Oliveira    schedule 18.07.2012