我找不到任何好的用途,但我确实发现了字符串文字的一些显着差异。关于复合文字的章节只出现了一次“未定义”一词,并且可以看出,它通常不适用于赋值或其他修改:
16 请注意,如果使用迭代语句而不是显式 goto 和标记语句,则未命名对象的生命周期将仅是循环的主体,并且在下次进入时 p 将具有不确定的值,这将导致在未定义的行为中。
所以“它是未定义的行为”的答案似乎是:“不,不是。”
此外,另一个区别是寿命。虽然字符串文字总是有静态存储复合文字没有:
5 复合文字的值是由初始化列表初始化的未命名对象的值。如果复合文字出现在函数体之外,则该对象具有静态存储持续时间;否则,它具有与封闭块关联的自动存储持续时间。
这意味着这完全没问题:
char *get_string() {
return "Foobar"; // Ok! Static storage
}
但这不是:
struct my_struct {
int x;
int y;
};
struct my_struct *get_my_struct() {
return &(struct my_struct){0,0}; // Not ok! Automatic storage
}
我也做了一个实验。我不是 100% 如何解释它,因为它既可以解释为静态存储,也可以解释为未定义的行为。这输出了“42”:
int main(void) {
struct my_struct *p = get_my_struct();
struct my_struct *t = get_my_struct();
p->x = 42;
printf("%d\n", t->x);
}
但是,当我打开-O2
或-O3
打印“0”时,我很确定这是未定义的行为。取决于优化级别的不同结果是 UB 的一个非常常见的症状。请注意,在我打开优化之前没有发出警告。当我这样做时,我得到了这个:
warning: ‘<Uf3f0>.x’ is used uninitialized in this function [-Wuninitialized]
16 | printf("%d\n", t->x);
| ^~~~~~~~~~~~~~~~~~~~
还有一点值得注意的是:
7 字符串文字和具有 const 限定类型的复合文字不需要指定不同的对象
这意味着两个没有const的复合文字应该指定不同的对象,但对于字符串文字来说并非如此。