Ошибка “элемент инициализации не является константой” при попытке инициализировать переменную с константой

Я получаю сообщение об ошибке в строке 6 (initialize my_foo для foo_init) следующей программы, и я не уверен, что понимаю почему.

typedef struct foo_t { int a, b, c; } foo_t; const foo_t foo_init = { 1, 2, 3 }; foo_t my_foo = foo_init; int main() { return 0; } 

Имейте в виду, что это упрощенная версия более крупного многофайлового проекта, над которым я работаю. objective состояла в том, чтобы иметь единую константу в объектном файле, которую могут использовать несколько файлов для инициализации государственной структуры. Поскольку это встроенная цель с ограниченными ресурсами, а структура не такая маленькая, я не хочу использовать несколько копий источника. Я бы предпочел не использовать:

 #define foo_init { 1, 2, 3 } 

Я также пытаюсь написать переносимый код, поэтому мне нужно решение, которое действительно C89 или C99.

Это связано с ORG в объектном файле? Эти инициализированные переменные попадают в один ORG и инициализируются путем копирования содержимого второго ORG?

Может быть, мне просто нужно будет изменить свою тактику, и у меня есть функция инициализации для всех копий при запуске. Разве есть другие идеи?

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

«Большой» объект никогда не является постоянным выражением в C, даже если объект объявлен как const .

Более того, в языке C термин «константа» относится к литеральным константам (например, 1 , 'a' , 0xFF и т. Д.), Перечисляемым членам и результатам таких операторов, как sizeof . Объекты Const-certified (любого типа) не являются константами в терминологии языка C. Они не могут использоваться в инициализаторах объектов со статической продолжительностью хранения, независимо от их типа.

Например, это НЕ постоянное

 const int N = 5; /* `N` is not a constant in C */ 

Вышеуказанное N будет константой в C ++, но оно не является константой в C. Итак, если вы попытаетесь сделать

 static int j = N; /* ERROR */ 

вы получите ту же ошибку: попытка инициализировать статический объект с непостоянной.

Вот почему на языке C мы преимущественно используем #define для объявления именованных констант, а также прибегаем к #define для создания именованных агрегатных инициализаторов.

Это ограничение языка. В разделе 6.7.8 / 4:

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

В разделе 6.6 спецификация определяет, что должно рассматриваться как постоянное выражение. Нет, где указано, что константная переменная должна рассматриваться как постоянное выражение. Для компилятора законно распространять это ( 6.6/10 - An implementation may accept other forms of constant expressions ), но это ограничивает переносимость.

Если вы можете изменить my_foo так что у него нет статического хранилища, вам будет хорошо:

 int main() { foo_t my_foo = foo_init; return 0; } 

Просто для иллюстрации с помощью сравнения и контрастности. Код находится с http://www.geeksforgeeks.org/g-fact-80/ / Код выходит из строя в gcc и проходит в g ​​++ /

  #include int initializer(void) { return 50; } int main() { int j; for (j=0;j<10;j++) { static int i = initializer(); /*The variable i is only initialized to one*/ printf(" value of i = %d ", i); i++; } return 0; } 

Это немного устарело, но я столкнулся с подобной проблемой. Вы можете сделать это, если используете указатель:

 #include  typedef struct foo_t { int a; int b; int c; } foo_t; static const foo_t s_FooInit = { .a=1, .b=2, .c=3 }; // or a pointer static const foo_t *const s_pFooInit = (&(const foo_t){ .a=2, .b=4, .c=6 }); int main (int argc, char **argv) { const foo_t *const f1 = &s_FooInit; const foo_t *const f2 = s_pFooInit; printf("Foo1 = %d, %d, %d\n", f1->a, f1->b, f1->c); printf("Foo2 = %d, %d, %d\n", f2->a, f2->b, f2->c); return 0; } 
  • Легкий способ найти неинициализированные переменные-члены
  • Что такое идеальный аналог в Python для «пока не EOF»,
  • Почему локальные переменные не инициализируются в Java?
  • Инициализация указателя в отдельной функции в C
  • Как эмулировать инициализацию массива C "int arr = {e1, e2, e3, ...}" поведение с std :: array?
  • Что такое динамическая инициализация объекта в c ++?
  • Что такое блок инициализации?
  • Эффективность Java «Инициализация двойного брекета»?
  • Как инициализировать массив объектов в Java
  • Есть ли разница между инициализацией копирования и прямой инициализацией?
  • Почему C ++ 11 не поддерживает назначенные списки инициализаторов как C99?
  • Interesting Posts

    Прочтите файл .CSV в C

    Как добавить внешние библиотеки jar в проект android из командной строки

    Каково возможное использование для параметра #define для if (false) {} else for??

    В Java, как найти, является ли первый символ в строке верхним регистром без регулярного выражения

    Игнорировать недопустимый самоподписанный сертификат ssl в node.js с https.request?

    как развернуть / развернуть (лить / расплавить) фрейм данных?

    Спецификатор преобразования длинного двойника в C

    Как избежать ошибок «дублирования символа» в xcode с помощью общих статических библиотек?

    Можем ли мы пригласить людей использовать наше приложение или отправить запрос друга из приложения через Facebook в iOS 5?

    Как можно объединить две строки?

    Перенос фотографий с Mac на iPhone5

    Является ли строка в массиве?

    Фрагменты в Android 2.2.1, 2.3, 2.0. Это возможно?

    Импортировать обычный файл CSS в файл SCSS?

    iter_swap () и swap () – в чем разница?

    Давайте будем гением компьютера.