在 C 中使用整数转换的全局变量指针初始化全局变量
Initializing a global variable with integer-casted global variable pointer in C
我发现了一个意外的 'invalid' 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;
在 全局 space 中。 语句 不允许存在于全局范围内。它需要在功能范围内。
一种特殊情况,定义时初始化是允许的,但条件是初始化器必须是编译时常量。
这里,str
不是编译时常量值。因此错误。
FWIW,"test string"
是一个未命名的 字符串文字 ,允许用作初始值设定项。所以,第一个语句是允许的。
此外,使用 int pstr2 = (int)str;
是危险的,因为无法保证指针是否适合 int
。
如果这段代码是全局级别的,即在函数之外,则第二行确实无效。全局变量只能用常量表达式初始化。
任何其他内容都是语句,必须驻留在函数中。
Which part of C specification makes this erroneous?
由于pstr
是全局的,所以它有静态存储期限。因此,C99标准的第6.7.8.4节适用:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
"test string"
的地址要到link 时才能解析,而将地址转换为int
需要对link 时的值进行计算。这使得 (int)str
在此上下文中无效。
注意link-时间常数无需计算是允许的,例如
char *pstr = str;
完全有效,因为没有转换。
注意: 由于 int
不能保证完整保存指针,请考虑使用 intptr_t
或 uintptr_t
类型。
这不是常量,因为转换为 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;
所以问题不在于演员表本身。
我发现了一个意外的 'invalid' 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;
在 全局 space 中。 语句 不允许存在于全局范围内。它需要在功能范围内。
一种特殊情况,定义时初始化是允许的,但条件是初始化器必须是编译时常量。
这里,str
不是编译时常量值。因此错误。
FWIW,"test string"
是一个未命名的 字符串文字 ,允许用作初始值设定项。所以,第一个语句是允许的。
此外,使用 int pstr2 = (int)str;
是危险的,因为无法保证指针是否适合 int
。
如果这段代码是全局级别的,即在函数之外,则第二行确实无效。全局变量只能用常量表达式初始化。
任何其他内容都是语句,必须驻留在函数中。
Which part of C specification makes this erroneous?
由于pstr
是全局的,所以它有静态存储期限。因此,C99标准的第6.7.8.4节适用:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
"test string"
的地址要到link 时才能解析,而将地址转换为int
需要对link 时的值进行计算。这使得 (int)str
在此上下文中无效。
注意link-时间常数无需计算是允许的,例如
char *pstr = str;
完全有效,因为没有转换。
注意: 由于 int
不能保证完整保存指针,请考虑使用 intptr_t
或 uintptr_t
类型。
这不是常量,因为转换为 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;
所以问题不在于演员表本身。