在C中使用整型全局变量指针初始化全局变量

在C中使用整型全局变量指针初始化全局变量,c,compiler-errors,initialization,standards,specifications,C,Compiler Errors,Initialization,Standards,Specifications,我发现一个意外的“无效”C代码段,我认为它是有效的: char str[] = "test string"; int pstr2 = (int)str; 第二行引发以下编译错误: main.c:2:12: error: initializer element is not a compile-time constant int pstr = (int)str; ^~~~~~~~ 1 error generated. 似乎浇铸的全局变量不是编译时常量,尽管正常的是。C规范

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

char str[] = "test string";
int pstr2 = (int)str;
第二行引发以下编译错误:

main.c:2:12: error: initializer element is not a compile-time constant
int pstr = (int)str;
           ^~~~~~~~
1 error generated.
似乎浇铸的全局变量不是编译时常量,尽管正常的是。C规范的哪一部分导致第二行错误


p.S.我刚刚编写了代码来重现我遇到的LLVM后端错误。不管怎样,谢谢你的提示:)

我相信,你做得很好

int pstr = (int)str;
在全球空间。全局范围中不允许存在语句。它需要在功能范围内

一种特殊情况是,允许在定义时初始化,但条件是初始值设定项必须是编译时常量

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

FWIW,
“测试字符串”
是允许用作初始值设定项的未命名字符串文本。因此,第一个语句是允许的


另外,使用
intpstr2=(int)str是危险的,因为不能保证指针是否适合
int

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

其他任何内容都是语句,必须驻留在函数中

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

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

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

“测试字符串”
的地址在链接时间之前无法解析,将地址强制转换为
int
需要对链接时间值进行计算。这使得
(int)str
在此上下文中无效

请注意,允许不进行计算的链路时间常数,例如

char *pstr = str;
是完全有效的,因为没有演员阵容


<强>注: >由于代码“INT/INSCOR>”不能保证指针的完整性,请考虑使用<代码> INTPrtRt><代码>或<代码> uint pTrtRt><代码>类型。

< P>这不是固定的,因为对INT/CUD>的转换可能需要转换,例如在Linux X8664 64系统上,在这里,代码
为4,而
sizeof(void*)
为8。通常,将指针强制转换为整数类型可能总是需要转换,即使您使用
intptr\u t
(您应该…),因为这实际上可能比指针大

相比之下,以下代码可以工作:

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

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

关于
(int)str
,什么不是常数?您在
(int)str
中看到了什么可执行代码?编辑后将其称为语句您如何知道地址适合
int
?我只是试图“编造”代码以重现LLVM后端错误。当然,我不会在实践中使用这种代码:)感谢您参考该标准。但是,如果由于您提到的原因,将“test string”的地址视为非常量,“char*pstr=str”不也应该引发编译错误吗?因此,如果链接时间常量与任何表达式(而不是其本身)组合,则它们似乎失去了常量性。谢谢:)