Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 作为参数传递的复合文本的生存期是多少?_C_Struct_Compound Literals - Fatal编程技术网

C 作为参数传递的复合文本的生存期是多少?

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(

这将使用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( &(someType) {
    .option = SOMEOPT
  });
  // do something else with typePtr
}
  • 这是有效的C吗

  • 如果是:复合文字的寿命是多少


  • 它在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