2

全て、

コンパイルすると、以下のCコードがあります。

static struct 
{
    const char* val;
    const char* parse_key;
    int len;  //parse key length
    void (*parse_routine) (const char* after, rtsp_sdp_t* response);
} sdp_header[] =
{
#define SDP_FILL_STRUCT(a,b) {#a, b, strlen(b), sdp_##a}
    SDP_FILL_STRUCT(attr_control, "a=control:"),    
    SDP_FILL_STRUCT(attr_framerate,"a=framerate:"),
    SDP_FILL_STRUCT(attr_range, "a=range:"),    
    {'\0', '\0', 0, (void*)0},  

};

以下のエラーが発生する理由:

:330: warning: initializer element is not constant
:330: warning: (near initialization for 'sdp_header[0]')
:331: warning: initializer element is not constant
:331: warning: (near initialization for 'sdp_header[1]')
:332: warning: initializer element is not constant
:332: warning: (near initialization for 'sdp_header[2]')
:333: warning: initializer element is not constant

原因がよくわかりません、どなたか教えてください。ありがとう

4

2 に答える 2

5

C89/90 では、中括弧で囲まれたすべての初期化子は定数である必要がありました。C99 以降では、静的ストレージ期間を持つオブジェクトのブレースで囲まれた初期化子は定数でなければなりません。

これはあなたの場合です:sdp_headerは静的なストレージ期間を持つ配列です。つまり、{}.

すべての初期化子は定数以外の定数であるstrlenようです。関数呼び出しは定数を生成しません。strlen特定のケースでは、次のように置き換えることができますsizeof

#define SDP_FILL_STRUCT(a,b) {#a, b, sizeof b - 1, sdp_##a}

bただし、リテラル文字列を表す場合にのみ機能します(これはあなたの例の場合です)。

また、意図に応じて、最後の初期化子が間違っているか誤解を招く可能性があります。val最後のparse_key要素の値は何ですか? 空の文字列が必要な場合は、次のようにする必要があります

{ "", "", 0, NULL }

nullポインターが必要な場合は、次のようにする必要があります

{ NULL, NULL, 0, NULL }

また

{ 0, 0, 0, 0 }

または単なる

{ 0 }

あなたの current'\0'はヌルポインター定数として機能しますが、ヌルポインター定数を指定するのは誤解を招く奇妙な方法です。

また、関数ポインター メンバーを使用して0いる理由も不明です。void *なんで?単に書くNULLかプレーン0。キャスト不要。キャストが必要な場合は、少なくとも適切な型にキャストしてください。どこvoid *から来たの?

于 2013-11-04T06:09:27.340 に答える
3

その理由は2つの問題です:

const char* val;
const char* parse_key;

#define SDP_FILL_STRUCT(a,b) {#a, b, strlen(b), sdp_##a} //strlen(b)

問題 1:

strlenはコンパイル時に評価されないので、コンパイラは不平を言います..strlenコードの実行中にのみ評価されます。

一部のコンパイラはコンパイル時の定数に最適化できる場合がありますが、それは、実行しようとしていることが許可されていると仮定することを有効にしないことに注意してください。

問題 2: (ソース: https://stackoverflow.com/a/3025106/1253932 )

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

たとえば、これは定数ではありません

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

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

static int j = C; /* ERROR */

同じエラーが発生します。静的オブジェクトを非定数で初期化しようとしています。

于 2013-11-04T05:19:28.860 に答える