错误:初始化元素不是常量

时间:2012-03-27 05:56:25

标签: c static structure

#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);
}

我知道如果我在函数范围初始化my_third它可以正常工作“在C中,具有静态存储持续时间的对象,例如在文件范围内声明的对象只能使用常量表达式初始化”,否则它会给我:

错误:初始化元素不是常量 new.c:41:错误:(接近初始化`my_third [0] .q')

现在我的问题是:如果没有在函数内移动表达式,是否有任何解决方法。我无法移动,因为我的代码中的许多地方都使用了这些结构。

如果您需要更多信息,请与我们联系。

3 个答案:

答案 0 :(得分:1)

丑陋的方式:

#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;
}

给出:

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

答案 1 :(得分:0)

怎么样

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

因为这正是你得到的价值吗?

为了使更改更容易,您可以包装诸如

之类的图层
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}};

然后只需更改#define以保持my_secondmy_third同步。

另一种选择可能是将THIRD_T更改为包含SECOND_T而不是FIRST_T。然后(也许)让#define做简化访问:

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

#define q qq->p

这样

my_third->q

变得有效

my_third->qq->p

答案 2 :(得分:0)

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

当您声明此结构const的变量时,其所有成员都变为const,因为它们存储在ROM中。 int const x;int const y;等。对于指针,这意味着它变为FIRST_T * const p;。也就是说,const指针指向非常量数据。指向的类型仍然不是const!我怀疑这就是你遇到问题的原因。

{1,2,3,p1},

p1是数组类型并衰减为const FIRST_T p1* const(常量指针指向常量数据)。您尝试将此值分配给FIRST_T * const p;(指向非常量数据的常量指针)。要解决此问题,请尝试将类型声明为

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;

使用MinGW测试,GCC 4.6.2。

  • -std = c99 -pedantic编译好。
  • -std = c89 -pedantic发出警告。 “警告:初始化元素在加载时不可计算[默认情况下启用]”。

(我不确定这个案例的标准之间的区别,所以我宁愿不推测为什么它在C99而不是C89。可能与VLA有关?)