c - 作为具有静态持续时间的对象的初始值设定项的指针
c - pointer as an initializer for an object with static duration
我。问题的背景。
关于标准的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.
至于6.2.4。 3) 标准:
An object whose identifier is declared with external or
internal linkage, or with the storage-class specifier static
has static storage duration.
至于6.6。 7) 标准:
More latitude is permitted for constant expressions in
initializers.
和 6.6。 9):
An address constant is a null pointer,a pointer to an lvalue designating
an object of static storage duration, or a pointer to a function
designator; ...
终于在6.3.2.1。 1) 我们阅读:
An lvalue is an expression with an object type or an incomplete type
other than void;
二.问题.
我在 object.h
中有以下声明:
struct class_check_s {
char blank;
};
struct class_check_s class_check = { 0 };
struct class_check_s *passed = &class_check;
struct object_vt_s {
/* ... */
struct class_check_s *safecheck;
/* ... */
};
object.h
被 includ
编辑成 object.c
,其中我有以下代码:
struct object_vt_s object_vt = {
/* ... */
.safecheck= passed,
/* ... */
};
gcc
对 .safecheck= passed
部分大喊:
error: initializer element is not constant
clang
类似:
error: initializer element is not a compile-time constant
但我认为我的情况低于 6.6。 9).我猜不会?我找不到确切原因的答案。
我正在做的是一个主要用于学习目的的小 oop 模块。我正在尝试在对象的“方法”内部实现某种动态类型检查。
6.6 9 中“指向左值的指针……”的意思是 pointer-value 左值,即左值的地址。虽然您的 struct class_check_s *passed
被称为“指针”,但更具体地说,它是一个值为指针的对象。当你写 .safecheck = passed
时,你并没有给编译器它想要的初始化值;你告诉它从 passed
.
中获取值
你可以写 .safecheck = &class_check
。这会将 safecheck
初始化为 class_check
的地址,并且编译器能够向链接器描述该地址,以便程序加载器可以在程序启动时正确调整其值。
但是,对于 .safecheck = passed
,编译器名义上必须从存储中读取 passed
的值。理论上,一个好的编译器可以查看 passed
的初始化,看到它被初始化为 &class_check
,并使用该值进行初始化。 C 标准并没有正式禁止这样做,但它并不要求这样做,而且这是不寻常的。此外,请注意这里的语义有点不稳定:passed
未声明 [=21=],因此它的值可能会更改,那么为什么在编译 .safecheck = passed
时要使用它的任何特定值?当然,这都是“compile-time”的东西,但那是在 C 语言中添加 C 标准未指定的语义。就 C 的语义而言,passed
在程序开始执行之前不存在(没有为其保留存储空间)。
我。问题的背景。
关于标准的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.
至于6.2.4。 3) 标准:
An object whose identifier is declared with external or internal linkage, or with the storage-class specifier static has static storage duration.
至于6.6。 7) 标准:
More latitude is permitted for constant expressions in initializers.
和 6.6。 9):
An address constant is a null pointer,a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; ...
终于在6.3.2.1。 1) 我们阅读:
An lvalue is an expression with an object type or an incomplete type other than void;
二.问题.
我在 object.h
中有以下声明:
struct class_check_s {
char blank;
};
struct class_check_s class_check = { 0 };
struct class_check_s *passed = &class_check;
struct object_vt_s {
/* ... */
struct class_check_s *safecheck;
/* ... */
};
object.h
被 includ
编辑成 object.c
,其中我有以下代码:
struct object_vt_s object_vt = {
/* ... */
.safecheck= passed,
/* ... */
};
gcc
对 .safecheck= passed
部分大喊:
error: initializer element is not constant
clang
类似:
error: initializer element is not a compile-time constant
但我认为我的情况低于 6.6。 9).我猜不会?我找不到确切原因的答案。
我正在做的是一个主要用于学习目的的小 oop 模块。我正在尝试在对象的“方法”内部实现某种动态类型检查。
6.6 9 中“指向左值的指针……”的意思是 pointer-value 左值,即左值的地址。虽然您的 struct class_check_s *passed
被称为“指针”,但更具体地说,它是一个值为指针的对象。当你写 .safecheck = passed
时,你并没有给编译器它想要的初始化值;你告诉它从 passed
.
你可以写 .safecheck = &class_check
。这会将 safecheck
初始化为 class_check
的地址,并且编译器能够向链接器描述该地址,以便程序加载器可以在程序启动时正确调整其值。
但是,对于 .safecheck = passed
,编译器名义上必须从存储中读取 passed
的值。理论上,一个好的编译器可以查看 passed
的初始化,看到它被初始化为 &class_check
,并使用该值进行初始化。 C 标准并没有正式禁止这样做,但它并不要求这样做,而且这是不寻常的。此外,请注意这里的语义有点不稳定:passed
未声明 [=21=],因此它的值可能会更改,那么为什么在编译 .safecheck = passed
时要使用它的任何特定值?当然,这都是“compile-time”的东西,但那是在 C 语言中添加 C 标准未指定的语义。就 C 的语义而言,passed
在程序开始执行之前不存在(没有为其保留存储空间)。