10

使用 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
}
  1. 这甚至是有效的C吗?

  2. 如果是这样:复合文字的生命周期是多少?

4

2 回答 2

10

它是 C99 或更高版本的有效 C。

C99 §6.5.2.5复合文字

复合文字的值是由初始化列表初始化的未命名对象的值。如果复合文字出现在函数体之外,则该对象具有静态存储持续时间;否则,它具有与封闭块关联的自动存储持续时间。

在您的示例中,复合文字具有自动存储功能,这意味着它的生命周期在其块内,即main()它所在的函数。

@Shafik Yaghmour 推荐阅读:

  1. 新 C:复合字面量
  2. GCC 手册:6.25 复合文字
于 2014-02-19T13:57:13.327 回答
4

余皓已经用标准回答了,现在有些庸俗了。

每当您看到复合文字时:

struct S *s;
s = &(struct S){1};

您可以将其替换为:

struct S *s;
struct S __HIDDEN_NAME__ = {1};
s = &__HIDDEN_NAME__;

所以:

主程序

#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
}

完整编译命令:

gcc -fsanitize=undefined -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
于 2015-07-02T08:08:22.003 回答