web-dev-qa-db-ja.com

constで変数を初期化しようとすると、エラー「初期化子要素は定数ではありません」

次のプログラムの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のソリューションが必要です。

これはオブジェクトファイル内のORGに関係していますか?初期化された変数は1つのORGに入り、2番目のORGの内容をコピーすることで初期化されますか?

たぶん、戦術を変更するだけで、起動時にすべてのコピーを初期化機能で実行することができます。他にアイデアがない限り?

169
tomlogic

C言語では、静的ストレージ期間を持つオブジェクトは、定数式で、または定数式を含む集約初期化子で初期化する必要があります。

「大」オブジェクトは、オブジェクトがconstとして宣言されている場合でも、Cの定数式になることはありません。

さらに、C言語では、「定数」という用語はリテラル定数1'a'0xFFなど)、enumメンバー、およびsizeofなどの演算子の結果を指します。 (任意の型の)定数で修飾されたオブジェクトは、C言語の用語では定数ではないです。タイプに関係なく、静的ストレージ期間を持つオブジェクトの初期化子では使用できません。

たとえば、これはNOT定数です

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

上記のNはC++では定数ですが、Cでは定数ではありません。

static int j = N; /* ERROR */

同じエラーが表示されます。つまり、静的オブジェクトを非定数で初期化しようとします。

これが、C言語で主に#defineを使用して名前付き定数を宣言し、#defineを使用して名前付き集計イニシャライザーを作成する理由です。

241
AnT

これは言語の制限です。セクション6.7.8/4で:

静的ストレージ期間を持つオブジェクトの初期化子のすべての式は、定数式または文字列リテラルでなければなりません。

セクション6.6では、仕様は定数式と見なされるものを定義しています。 const変数を定数式と見なす必要があるとはどこに記載されていません。コンパイラがこれ(6.6/10 - An implementation may accept other forms of constant expressions)を拡張することは正当ですが、それは移植性を制限します。

my_fooを変更して静的ストレージがない場合は、大丈夫です:

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

比較と対比による説明のためだけにコードは http://www.geeksforgeeks.org/g-fact-80/ /からのものです。 g ++/を渡します

#include<stdio.h>
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;
}
5
achoora

これは少し古いですが、私は同様の問題に遭遇しました。ポインターを使用する場合、これを行うことができます。

#include <stdio.h>
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;
}
2
valenumr