引用的复合数组文字的生命周期

Dol*_*000 4 c compound-literals

我最近才知道我实际上可以在C语言中使用复合文字数组的引用,我发现它很有用,但我不太明白它是如何工作的.

例如,假设我使用该功能来避免为一个调用声明一个变量的一些套接字接口函数,我不关心返回名称长度,如下所示:

int sockfamily(int fd)
{
    struct sockaddr_storage ss;

    getpeername(fd, (struct sockaddr *)&ss, (socklen_t [1]){sizeof(ss)});
    return(ss.ss_family);
} 
Run Code Online (Sandbox Code Playgroud)

显然,sizeof(ss)需要实际存储在堆栈上以便将指向它的指针传递给getpeername堆栈,因此必须为此分配和保留堆栈上的空间,但这个分配的生命周期是多少?我可以信任多久才能保持分配?

看一下GCC的汇编输出,我观察到如果我把调用getpeername放在一个循环中,那么分配不会在循环的多次迭代中存活,但是其他条件可能导致它不再存在?

eca*_*mur 11

函数中定义的复合文字具有与包含它的块相关联的自动生命周期(即与在同一级别上声明的变量相同的生命周期).这在6.5.2.5p5标准中规定.

int f() {
    for (int i = 0; i < 10; ++i) {
        int *j = (int []){i};  // storage duration of loop body
    }
} 
Run Code Online (Sandbox Code Playgroud)

这实质上意味着复合文字等同于在同一范围内声明和初始化的变量:

int f() {
    for (int i = 0; i < 10; ++i) {
        int __unnamed[] = {i};
        int *j = __unnamed;
    }
} 
Run Code Online (Sandbox Code Playgroud)

如果将复合文字传递给指针在其生命周期内持续存在的任何地方,请注意:

int f() {
    int *p;
    if (1) {
        p = (int []){0, 1, 2};
        assert(p[0] == 0);
    }
    // *p is undefined
}
Run Code Online (Sandbox Code Playgroud)