简体   繁体   中英

error: initializer element is not constant

#include <stdio.h>

typedef struct {
  int a;
  int b;
  int c;
} FIRST_T;

typedef struct {
  int x;
  int y;
  int z;
  FIRST_T *p;
} SECOND_T;

typedef struct {
  int a1;
  int a2;
  int a3;
  FIRST_T *q;
}THIRD_T;

const FIRST_T p1[]={{1,2,3},{3,4,5},{6,7,8}};
const FIRST_T p2[]={{4,5,12},{7,8,9}};
const SECOND_T my_second[]=
{
  {1,2,3,p1},
  {4,5,6,p2}
};
const THIRD_T my_third[] = {{1,2,3,my_second[1].p},{4,5,6,my_second[0].p}};

int main() {
  //const THIRD_T my_third[] = {{1,2,3,my_second[1].p},{4,5,6,my_second[0].p}};
  printf("%d %d %d %d \n", 
         my_third[0].a1,
         my_third[0].a2,
         my_third[0].a3,
         my_third[0].q[1].c);
}

I know if I initialize my_third in the function scope it works fine as "In C, objects with static storage duration such as objects declared at file scope can only be initialized with constant expressions" else it gives me:

error: initializer element is not constant new.c:41: error: (near initialization for `my_third[0].q')

Now my question is: Is there any workaround for me without moving the expression inside function. I can't move as these structures are used in many places in my code.

Please let me know if you need more information.

An ugly way:

#include <stdio.h>

struct first_t {
    int a;
    int b;
    int c;
};

struct second_t {
    int x;
    int y;
    int z;
    const struct first_t *p;
};

struct third_t {
    int a1;
    int a2;
    int a3;
    const struct first_t *q;
};

const struct first_t p1[] = {
    {1, 2, 3},
    {3, 4, 5},
    {6, 7, 8}
};
const struct first_t p2[] = {
    {4, 5, 12},
    {7, 8, 9}
};
const struct second_t my_second[] = {
    {1, 2, 3, p1},
    {4, 5, 6, p2}
};
const struct third_t  my_third[] = {
    {1, 2, 3, (const struct first_t*)&my_second[1].p},
    {4, 5, 6, (const struct first_t*)&my_second[0].p}
};

int main(void) {
    fprintf(stdout,
        "PRNT: %d %d %d %d\n",
        my_third[0].a1,
        my_third[0].a2,
        my_third[0].a3,
        my_third[0].q[1].c
    );

    return 0;
}

Gives:

/* gcc -Wall -Wextra -pedantic -std=c89 -ggdb -o bad fmts.c && ./bad
 *
 * PRNT: 1 2 3 4
 *
 * */

what about

const THIRD_T my_third[] = {{1,2,3,p2},{4,5,6,p1}};

as it is exactly the value you'll get?

In order to make changes easier, you could wrap a layer such as

const FIRST_T p1[]={{1,2,3},{3,4,5},{6,7,8}};
const FIRST_T p2[]={{4,5,12},{7,8,9}};

#define first_p p1
#define second_p p2

const SECOND_T my_second[]=
{
{1,2,3,first_p},
{4,5,6,second_p}
};
const THIRD_T my_third[] = {{1,2,3,second_p},{4,5,6,first_p}};

and then just change the #define s in order to keep my_second and my_third in sync.

Another option could be to change THIRD_T to contain a SECOND_T instead of a FIRST_T . and then (maybe) have a #define do simplify access:

typedef struct {
int a1;
int a2;
int a3;
SECOND_T *qq;
}THIRD_T;

#define q qq->p

so that

my_third->q

becomes effectively

my_third->qq->p

.

typedef struct {
    int x;
    int y;
    int z;
    FIRST_T *p;
} SECOND_T;

When you declare a variable of this struct const , all its members become const , as in they get stored in ROM. int const x; , int const y; etc. For the pointer, this means that it turns FIRST_T * const p; . That is, a const pointer to non-constant data. The pointed-to type is still not const however! I suspect this is why you get problems.

{1,2,3,p1},

p1 is of array type and decays into a const FIRST_T p1* const (constant pointer to constant data). You try to assign this to a FIRST_T * const p; (constant pointer to non-constant data). To fix this, try to declare the types as

typedef struct {
  int x;
  int y;
  int z;
  const FIRST_T *p;
} SECOND_T;

typedef struct {
  int a1;
  int a2;
  int a3;
  const FIRST_T *q;
} THIRD_T;

Tested with MinGW, GCC 4.6.2.

  • -std=c99 -pedantic compiles fine.
  • -std=c89 -pedantic gives warnings. "warning: initializer element is not computable at load time [enabled by default]".

(I'm not sure of the difference between the standards for this case so I'd rather not speculate why it works in C99 and not C89. Might be related to VLA?)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM