错误:初始化元素在分配结构指针时不是常量

时间:2015-11-26 08:42:02

标签: c linux pointers gcc

我可以在一个IDE中成功编译这个c代码(使用c99编译器) 但不是在linux下使用gcc

#define MAX_STRUCT 3

sstructtype SStructrecord1, SStructrecord2, SStructrecord3;
u32 RecordStructAdd[MAX_STRUCT] = {(u32)&SStructrecord1, (u32)&SStructrecord2, (u32)&SStructrecord3};

我也试过分配个别值,但仍然是同样的错误。我在这里做错了什么?

error: initializer element is not constant
error: (near initialization for ‘RecordStructAdd[0]’)

1 个答案:

答案 0 :(得分:2)

问题是演员。如果只是将指针存储为指针,那么编译器就不会抱怨:

#define MAX_STRUCT 3

sstructtype SStructrecord1, SStructrecord2, SStructrecord3;
sstructtype *RecordStructAdd[MAX_STRUCT] = {&SStructrecord1, &SStructrecord2, &SStructrecord3};

以下是一个简短的解释:

编译器生成包含可重定位代码的可执行文件。可执行文件中的地址是占位符,必须在运行时由加载程序修复。为了帮助加载器完成它的工作,可执行文件包含一个relocation table,它指定在加载可执行文件时必须用哪些实际地址替换哪些占位符地址。

因此,如果将对象的地址存储在静态变量中,则可执行文件将在重定位表中有一个条目,允许加载程序在加载时将正确的地址放入静态变量中。

但是如果地址是64位,并且U32是32位,那么将指针转换为U32只会存储地址的一部分,而不是完整地址。重定位表没有修复部分地址的机制。因此,转换为较小类型的指针不是编译时常量。

以下是C规范在§6.6第7段中所说的内容:

  

6.6常量表达式

     

...

     

7初始值设定项中的常量表达式允许更多的纬度。   这样的常数表达式应该是或者评估为其中之一   以下内容:

     
      
  • 算术常量表达式
  •   
  • 一个空指针常量,
  •   
  • 地址常量,或
  •   
  • 完整对象类型的地址常量加上或减去整数常量表达式。
  •   

转换为U32的地址不是允许的常量表达式之一。但是指针和U32大小相同的实现可能会让你逃脱它。