C 作为参数传递的复合文本的生存期是多少?
这将使用clang编译而不发出警告C 作为参数传递的复合文本的生存期是多少?,c,struct,compound-literals,C,Struct,Compound Literals,这将使用clang编译而不发出警告 typedef struct { int option; int value; } someType; someType *init(someType *ptr) { *ptr = (someType) { .option = ptr->option | ANOTHEROPT, .value = 1 }; return ptr; } int main() { someType *typePtr = init(
typedef struct {
int option;
int value;
} someType;
someType *init(someType *ptr) {
*ptr = (someType) {
.option = ptr->option | ANOTHEROPT,
.value = 1
};
return ptr;
}
int main()
{
someType *typePtr = init( &(someType) {
.option = SOMEOPT
});
// do something else with typePtr
}
它在C99或更高版本中是有效的C C99§6.5.2.5复合文字 复合文字的值是由初始化的未命名对象的值 初始化列表。如果复合文字出现在函数体之外,则对象 具有静态存储时间;否则,它将具有与关联的自动存储持续时间 封闭块 在您的示例中,复合文字具有自动存储功能,这意味着它的生存期在其块内,即它所在的
main()
函数中
推荐阅读@Shafik Yaghmour:
余浩已经用标准回答了,现在有些庸俗化了 每当您看到复合文字时,如:
struct S *s;
s = &(struct S){1};
您可以将其替换为:
struct S *s;
struct S __HIDDEN_NAME__ = {1};
s = &__HIDDEN_NAME__;
因此:
main.c
#include <assert.h>
struct S {int i;};
/* static: lives for the entire program. */
struct S *s1 = &(struct S){1};
struct S *s2;
struct S *s3;
struct S *s4;
int f(struct S *s) {
return s->i + 1;
}
int main() {
/* Undefined behaviour: not defined yet.
* GCC 10 -fsanitize=undefined -ggdb3 -O0 -std=c99 gives at runtime:
* runtime error: member access within null pointer of type 'struct S' */
#if 0
assert(f(s2) == 1);
#endif
/* Lives inside main, and any function called from main. */
s2 = &(struct S){1};
/* Fine because now instantiated. */
assert(f(s2) == 2);
/* Only lives in this block. */
{
s3 = &(struct S){1};
/* Fine. */
assert(f(s3) == 2);
}
{
/* On GCC 10 -O0, this replaces s3 above due to UB */
s4 = &(struct S){2};
}
/* Undefined Behavior: lifetime has ended in previous block.
* On GCC 10, ubsan does not notice it, and the assert fails
* due to the s4 overwrite.*/
#if 0
assert(s3->i == 1);
#endif
}
如果你知道你正在使用的东西的名称,你是否尝试研究该功能。这两个很好的例子分别是1和2:它们都回答了你的问题。我读过这些(还有更多),但没有发现这个具体的例子。如果你更新过这个例子,为了清晰起见,请将变量重命名为s1(全局)、s2(主)和s3(子块)。最后一条评论对我来说似乎不正确,因为我认为你的意思是指s3,它确实超出了范围,但它将引用s2(s1被阴影遮盖)。很漂亮。您添加的s4案例很有趣,也很令人惊讶,“替换s3”是什么意思?如果它有相同的名字(s3),我可以看到它,但是为什么在两个不同的变量(s3和s4)之间会有任何交互作用呢?为什么使用函数f而不是直接测试值?最后一个断言没有使用f(),不确定这是故意的还是疏忽。@AllanWind s3和s4进入堆栈,在s3解除分配堆栈下降后,s4进入同一位置,O0真的是愚蠢和可预测的
f
用于随机位置,以显示子载波的生存期(有点明显,因为在堆栈上)。
gcc -fsanitize=undefined -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c