C里面的结构体的初始化和赋值还是挺好玩的。比如说有个结构体comp如下:

struct comp {
    int x;
    int y;
};

那么初始化comp类型变量的一般方法就是:

struct comp z1 = {2, 3};

如果不想按照struct comp对其成员定义的顺序(C89-style initializer)来初始化,可以用另一种形式(designated initializer):

struct comp z1 = {
    .y = 3,
    .x = 2,
};

效果是一样的。

如果在初始化时有些成员的值没有指定,默认为0。例如如下定义一个全0的结构体:

struct comp z1 = {};

所有这些初始化的方法在赋值时都没用了。如果z1是一个已经定义了的结构体,现在想让z1具有值{6, 7},只能:

z1.x = 6;
z1.y = 7;

或者:

struct comp z2 = {6, 7};
z1 = z2;

然后从第二种方法里可以得到一些启发,能不能直接一步做完?于是就有了C99中出现的一个方法:compound literal。还是以给z1赋值为例,使用方法如下:

z1 = (struct comp) {6, 7};

这就干净多了。其实也就相当于:

struct comp temp = {6, 7};
z1 = temp;

也不一定非得用常量,变量也行:

int i = 6, j = 7;
z1 = (struct comp) {i, j};

或者更花哨一点:

z2 = (struct comp) {
    .y = i,
    .x = j,
};

总的来说就是允许用初始化的语法来对结构体赋值了。

比较神奇的是compound literal是个左值,也就是说可以这样写:

struct comp z1 = {2, 3};
(struct comp) {6, 7} = z1;

虽然看上去不知道有啥用……

Note. 在传参时可能有点用。比如一个函数会修改形参,那传一个compound literal进去可以省却定义一个临时变量。

但不管咋说compound literal在结构体赋值时还是很有用的。

Links: