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

Я добираюсь, ошибка на строке 6 (инициализируйте 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;
}

Следует иметь в виду, что это - упрощенная версия большего, многофайлового проекта, я продолжаю работать. Цель состояла в том, чтобы иметь единственную константу в объектном файле, который несколько файлов могли использовать для инициализации структуры состояния. Так как это - встроенная цель с ограниченными ресурсами, и структура не является настолько маленькой, я не хочу несколько копий источника. Я предпочел бы не использовать:

#define foo_init { 1, 2, 3 }

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

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

Возможно, я должен буду просто изменить свою тактику и иметь функцию инициализации, делают все копии при запуске. Если нет другие идеи там?

175
задан alk 3 August 2015 в 14:14
поделиться

2 ответа

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

"Большой" объект никогда не является константным выражением в языке Си, даже если объект объявлен как const.

Более того, в языке Си термин "константа" относится к литеральным константам (таким как 1, 'a', 0xFF и так далее), членам перечисления и результатам таких операторов, как sizeof. Const-qualified объекты (любого типа) не являются константами в терминологии языка Си. Их нельзя использовать в инициализаторах объектов со статической длительностью хранения, независимо от их типа.

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

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

Приведенное выше N было бы константой в C++, но не является константой в C. Поэтому, если вы попытаетесь выполнить

static int j = N; /* ERROR */

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

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

252
ответ дан 23 November 2019 в 20:26
поделиться

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

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

В разделе 6.6 спецификация определяет, что должно считаться константным выражением. Нигде не сказано, что переменная const должна считаться константным выражением. Компилятор может расширить это определение (6.6/10 - Реализация может принимать другие формы константных выражений), но это ограничит переносимость.

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

int main()
{
    foo_t my_foo = foo_init;
    return 0;
}
73
ответ дан 23 November 2019 в 20:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: