提问人:Wör Du Schnaffzig 提问时间:4/9/2021 最后编辑:user3386109Wör Du Schnaffzig 更新时间:4/9/2021 访问量:85
通过引用类型或该类型的变量,从定义中初始化变量
Initialization of variables from within the definition by referencing the type or a variable of that type
问:
如此大量地使用至少一个标准(C99-current)所涵盖的初始化代码中的声明,还是gcc扩展? 所有成员初始化术语的共同点是,它们要么引用类型,要么从类型定义中引用该类型的成员/变量。
#include <stddef.h>
#include <stdlib.h>
struct node{
int size;
int offset;
int *ptr;
struct node *this;
} s = {sizeof(s), offsetof(struct node, offset), &s.offset, &s};
int main(void){
struct node *s = malloc(sizeof(*s));
free(s)
}
我用谷歌搜索了搜索词 backreferencing declaration from definition, backreferencing declaration from initialization, c initialization struct referencing declaration etc, but all just provide me between declaration and definition between states.我用谷歌搜索了一下,从定义中回溯引用声明,从初始化回溯声明,从初始化回指,从初始化回指,从初始化回溯但是,我想知道当我从定义中引用类型或该类型的成员/变量时,标准允许什么。
答:
这里没有什么奇怪的。当我们来到 时,初始化开始,声明完全完成。运算符需要一个完整的类型,您的结构就是该类型。例如,这不起作用:=
sizeof
struct x;
int n = sizeof x;
此外,就您而言,您不仅拥有完整的类型。您还声明了一个对象。正因为如此,两者都是完全有效的。s
&s.offset
&s
在某些情况下,反向引用不起作用。这是其中之一:
int x[] = { sizeof x };
这会产生以下错误:
error: invalid application of ‘sizeof’ to incomplete type ‘int[]’
2 | int x[] = {sizeof x};
通常,不能从声明列表中引用结构成员。例如,此代码具有未定义的行为:
typedef struct { int x; int y; } foo_t;
foo_t foo = { .x=5, .y=x }; // BAD, the order of initialization between x and y is not defined
但是,对于您的具体情况,这并不适用。首先,struct 定义以 - 从那里开始,它是一个完整的类型,在当前文件中具有完整的定义(迂腐地:在当前翻译单元中)。}
然后,您将遇到以下初始值设定项的情况:
sizeof(s)
.由于您有一个完整的类型(不是正向声明的结构或可变长度数组等),因此使用 是可以的。它生成一个整数常量表达式 (C17 6.6/6),并在编译时计算。sizeof
offsetof
与 .sizeof
&s.offset
和。这些是地址常量,一种常量表达式 (C17 6.6/7)。这些在初始值设定项列表中也是允许的,并且在编译时也会计算。&s
因此,所有初始值设定项都是常量表达式,这意味着初始值设定项列表是有效的。即使你要声明这个结构体的静态存储持续时间。
评论
{sizeof(s), offsetof(struct node, offset), &s.offset, &s}
struct node
struct node *s = malloc(sizeof(*s))