使用C中的整数转换全局变量指针初始化全局变量

时间:2015-07-06 13:32:38

标签: c compiler-errors initialization standards specifications

我发现了一个意外的'无效'C代码段,我认为它是有效的:

deep_dup

第二行引发了以下编译错误:

schema_mod = @schema.deep_dup

似乎一个转换的全局变量不是编译时常量,尽管正常的变量是。 C规范的哪一部分使第二行错误?

P.S。我刚刚编写了代码来重现我遇到的LLVM后端错误。无论如何,感谢您提示:)

4 个答案:

答案 0 :(得分:2)

  

C规范的哪一部分会导致这种错误?

由于pstr是全局的,因此它具有静态存储持续时间。因此,C99标准的第6.7.8.4节适用:

  

具有静态存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。

"test string"的地址在链接时间之前无法解析,并且将地址转换为int需要对链接时值执行计算。这使(int)str对此上下文无效。

请注意,不允许使用计算链接时间常量,例如

char *pstr = str;

完全有效,因为没有演员。

注意:由于无法保证int完全保留指针,因此请考虑使用intptr_tuintptr_t类型。

答案 1 :(得分:1)

我相信,你在做什么

int pstr = (int)str;
全局空间中的

。全局范围内不允许存在语句。它需要在功能范围内。

一个特殊情况,允许初始化定义,但条件是初始化程序需要是编译时常量。

这里,str不是编译时常量值。因此错误。

FWIW,"test string"是未命名的字符串文字,允许用作初始化程序。所以,第一个声明是允许的。

此外,使用int pstr2 = (int)str;是危险的,因为无法保证指针是否适合int

答案 2 :(得分:0)

如果这段代码处于全局级别,即在函数之外,则第二行确实无效。全局变量只能用常量表达式初始化。

其他任何声明都必须存在于函数中。

答案 3 :(得分:0)

这不是常数,因为转换为int可能需要转换,例如在Linux x86_64系统上,其中sizeof(int)为4,而sizeof(void *)为8.通常,即使您使用intptr_t,也应该转换为整数类型的指针总是需要转换。 ...),因为这实际上可能比指针大。

相反,以下代码可以使用:

typedef struct { char foo[1]; } test_t;
char str[] = "test string";
test_t *pstr2 = (test_t *)str;

所以问题不在于演员本身。