结构初始化中的调用函数

时间:2018-11-24 01:16:26

标签: c function struct

请考虑以下代码段:

struct my_struct {
     int a;
     int b;
     int c;
};


void my_func(unsigned long x)
{
    struct my_struct m[] = {
         { 0, 1, 2 },
         { 11, 22, htonl(x) },
         { 0x1, 0xa, 0xbb }
    };
    ...
}

在结构初始化块内调用函数是否合法/可移植?

2 个答案:

答案 0 :(得分:4)

是的,这是合法的,只要您使用 automatic 存储持续时间初始化对象(如您的示例)。对于静态存储持续时间不合法的对象,因为此类对象在其初始值设定项中仅允许恒定表达式。

还请记住,尽管在C中,初始化器表达式的求值相对于彼此不确定地排序。这意味着,如果您在初始化器之间有多个函数调用,而这些函数的结果取决于某些共享状态,则这些初始化器的行为可能无法预测

int foo()
{
  static int a;
  return ++a;
}

int main()
{
  struct { int x, y; } s = { foo(), foo() };
  /* Can be `{ 1, 2 }` or `{ 2, 1 }`... */
}

关于可移植性,可以注意到C89 / 90不允许这样做(在C89 / 90中,所有{}括起来的初始化器都必须是常量表达式,即使对于自动对象也是如此),但是最受欢迎的是C89无论如何,/ 90编译器都支持。

答案 1 :(得分:3)

  

在结构初始化块内调用函数是否合法/可移植?

Initialization (§6.7.8/1)

  

[...]

|     initializer-list:
|             designationopt initializer
|             initializer-list , designationopt initializer

〜> 初始化程序列表由初始化程序组成

Initialization (§6.7.8/4)

  

对于具有静态存储持续时间的对象,初始化器中的所有表达式都应为常量表达式或字符串文字

〜> 初始化程序由表达式组成。 (用于具有静态存储持续时间的对象的常量表达式)

Expressions (§6.5/1)

  

表达式是一个运算符和操作数的序列,它们指定值的计算,或者指定对象或函数,或者产生副作用,或者执行它们的组合。

〜> 函数调用是一个表达式。