ava*_*ans 4 c initialization declaration definition
Is such heavy use of backreferencing a declaration from the initialization code covered by at least one of the standards (C99-current) or is it a gcc extension? All the member initialization terms have in common that they either reference the type or a member/variable of that type from within the definition of the type.
#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)
}
Run Code Online (Sandbox Code Playgroud)
I googled around using the searchterms backreferencing declaration from definition, backreferencing declaration from initialization, c initialization struct referencing declaration etc, but all just provide me the differences between declaration and definition. However, i would like to know what is allowed by the standard when i reference the type or a member/variable of that type from within the definition.
通常,您不能从声明列表中引用结构成员。例如,此代码具有未定义的行为:
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
Run Code Online (Sandbox Code Playgroud)
但是,对于您的具体情况,这并不适用。首先,结构体定义结束于}- 从那里开始它是一个完整的类型,在当前文件中具有完整定义的东西(迂腐:在当前翻译单元中)。
然后你有这些初始化器的情况:
sizeof(s). 由于您有一个完整的类型(不是前向声明的结构或可变长度数组等),因此使用没问题sizeof。它产生一个整数常量表达式 (C17 6.6/6) 并在编译时计算。offsetof与 相同的处理sizeof。&s.offset和&s。这些是地址常量,一种类型的常量表达式 (C17 6.6/7)。这些也允许在初始化列表中,并且也在编译时计算。所以你所有的初始化器都是常量表达式——这意味着初始化器列表是有效的。即使您要使用静态存储持续时间声明此结构。
这里没有什么奇怪的。当我们来到 时=,初始化开始,声明完成。该sizeof运营商需要一个完整的类型,你的结构是。例如,这不起作用:
struct x;
int n = sizeof x;
Run Code Online (Sandbox Code Playgroud)
此外,在您的情况下,您不仅拥有完整的类型。您还声明了一个对象s。正因为如此,&s.offset和&s都是完全有效的。
在某些情况下,反向引用不起作用。这是一个:
int x[] = { sizeof x };
Run Code Online (Sandbox Code Playgroud)
这产生了这个错误:
error: invalid application of ‘sizeof’ to incomplete type ‘int[]’
2 | int x[] = {sizeof x};
Run Code Online (Sandbox Code Playgroud)