2

all,

I have below C code, when I compiling,

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},  

};

why it gives out bellow errors:

: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

I don't know exactly what's the reason, could you please give me some help. thanks

gladman
  • 1,208
  • 4
  • 19
  • 39

2 Answers2

5

In C89/90 all brace-enclosed initializers were required to be constants. In C99 and later brace-enclosed initializers for objects with static storage duration must be constants.

This is what you have in your case: sdp_header is an array with static storage duration, which means that you are only allowed to use constants between the {}.

It appears that all of your initializers are constants besides the strlen ones. Function call does not produce a constant. In your specific case you can replace strlen with sizeof

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

but it will work only if b stands for a literal string (which is the case in your example).

Also, your last initializer is either wrong or misleading, depending on your intent. What are the values of val and parse_key supposed to be in the last element? If you want empty strings, then it should be

{ "", "", 0, NULL }

If you want null pointers, then it should be

{ NULL, NULL, 0, NULL }

or

{ 0, 0, 0, 0 }

or even a mere

{ 0 }

Your current '\0' will work as a null-pointer constant, but it is a misleading and strange way to specify a null-pointer constant.

And why you are casing 0 to void * for the function pointer member is also unclear. Why? Just write NULL or plain 0. No cast necessary. And if you want a cast, at least cast it to the proper type. Where did void * come from?

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
3

Its because of 2 problems:

const char* val;
const char* parse_key;

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

Problem 1:

strlen is not evaluated at the time of compiling .. so the compiler complains .. strlen will be only evaluated while running the code.

Note that some compilers might be able to optimize it to a compile-time constant, but that doesn't make it valid to assume that you're allowed to do what you're trying to do.

Problem 2: (source : https://stackoverflow.com/a/3025106/1253932 )

In C language the term "constant" refers to literal constants (like 1, 'a', 0xFF and so on) and enum members. Const-qualified objects (of any type) are not constants in C language terminology. They cannot be used in initializers of objects with static storage duration, regardless of their type.

For example, this is NOT a constant

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

The above C would be a constant in C++, but it is not a constant in C. So, if you try doing

static int j = C; /* ERROR */

you will get the same error: an attempt to initialize a static object with a non-constant.

Community
  • 1
  • 1
sukhvir
  • 5,265
  • 6
  • 41
  • 43