使用复合文字对静态数组进行条件初始化

发布于 2025-01-15 08:50:11 字数 1386 浏览 2 评论 0原文

#include <stdint.h>

#define INIT_UINT32 1
#define INIT_INT32  2

#define INIT INIT_INT32

typedef union
{
  uint32_t a;
  int32_t  b;
} Foo_t;

/* Why does this compile... */
static Foo_t foo_static = INIT == INIT_INT32 ?
    (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX };

/* but this doesn't? */
static Foo_t foo_static_array[] =
{
  INIT == INIT_INT32 ? (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX }
};

int main(void)
{
}

编译时,使用复合文字的 foo_static 条件初始化成功,但使用复合文字的 foo_static_array 条件初始化失败。以下是编译错误。

$ gcc test.c
test.c:4:21: error: initializer element is not constant
    4 | #define INIT_INT32  2
      |                     ^
test.c:6:14: note: in expansion of macro ‘INIT_INT32’
    6 | #define INIT INIT_INT32
      |              ^~~~~~~~~~
test.c:21:3: note: in expansion of macro ‘INIT’
   21 |   INIT == INIT_INT32 ? (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX }
      |   ^~~~
test.c:4:21: note: (near initialization for ‘foo_static_array[0]’)
    4 | #define INIT_INT32  2
      |                     ^
test.c:6:14: note: in expansion of macro ‘INIT_INT32’
    6 | #define INIT INIT_INT32
      |              ^~~~~~~~~~
test.c:21:3: note: in expansion of macro ‘INIT’
   21 |   INIT == INIT_INT32 ? (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX }
      |   ^~~~

谁能解释为什么会这样?

#include <stdint.h>

#define INIT_UINT32 1
#define INIT_INT32  2

#define INIT INIT_INT32

typedef union
{
  uint32_t a;
  int32_t  b;
} Foo_t;

/* Why does this compile... */
static Foo_t foo_static = INIT == INIT_INT32 ?
    (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX };

/* but this doesn't? */
static Foo_t foo_static_array[] =
{
  INIT == INIT_INT32 ? (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX }
};

int main(void)
{
}

When compiled, the conditional initialization of foo_static using compound literals succeeds, but the conditional initialization of foo_static_array using compound literals fails. Following are the compile errors.

$ gcc test.c
test.c:4:21: error: initializer element is not constant
    4 | #define INIT_INT32  2
      |                     ^
test.c:6:14: note: in expansion of macro ‘INIT_INT32’
    6 | #define INIT INIT_INT32
      |              ^~~~~~~~~~
test.c:21:3: note: in expansion of macro ‘INIT’
   21 |   INIT == INIT_INT32 ? (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX }
      |   ^~~~
test.c:4:21: note: (near initialization for ‘foo_static_array[0]’)
    4 | #define INIT_INT32  2
      |                     ^
test.c:6:14: note: in expansion of macro ‘INIT_INT32’
    6 | #define INIT INIT_INT32
      |              ^~~~~~~~~~
test.c:21:3: note: in expansion of macro ‘INIT’
   21 |   INIT == INIT_INT32 ? (Foo_t){ .a = UINT32_MAX} : (Foo_t){ .b = INT32_MAX }
      |   ^~~~

Can anyone explain why this is the case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遗失的美好 2025-01-22 08:50:11

GCC 提供前一种初始化作为 C 标准的扩展。它没有提供后者。这是 GCC 的选择,不是标准强制要求的。对于-pedantic,GCC 抱怨两者。

C标准中的相关段落是C 2018 6.7.9 4:

具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。

这是在 Constraints 部分中,这意味着符合要求的编译器必须对其进行诊断,就像使用 -pedantic 时 GCC 所做的那样,尽管它仍然接受代码并完成编译。如果没有 -pedantic,GCC 接受两者,但仅诊断后者。

关于 C 扩展的 GCC 文档没有提及造成这种差异的原因。它的 条款 6.27 表示具有自动存储持续时间的聚合的初始值设定项不是要求是常量表达式,但 C 扩展子句中没有子子句来处理静态对象的初始值设定项。

为了使您的代码严格符合要求,您不应在非数组或数组初始化中使用这些初始值设定项。

GCC is providing the former initialization as an extension to the C standard. It is not providing the latter. This is a GCC choice, not mandated by the standard. With -pedantic, GCC complains about both.

The relevant passage in the C standard is C 2018 6.7.9 4:

All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.

This is in a Constraints section, which means a conforming compiler must diagnose it, as GCC does when -pedantic is used, although it still accepts the code and completes compilation. Without -pedantic, GCC accepts both but only diagnoses the latter.

The GCC documentation on C extensions is silent about the reason for this difference. Its clause 6.27 says that initializers for aggregates with automatic storage duration are not required to be constant expressions, but there is no subclause in the C extensions clause that addresses initializers for static objects.

To make your code strictly conforming, you should not use these initializers in either the non-array or the array initialization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文