微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

复合文字的赋值如何有用?

如何解决复合文字的赋值如何有用?

我正在阅读有关复合文字的信息,我发现它们是l值。因此,我怀疑您可以分配它们,因此我进行了一个实验,并注意到它在编译时没有警告,gcc -Wall -Wextra -pedantic

struct foo {
    int x;
    int y;
};

int main(void) {
    (struct foo){0,0} = (struct foo){1,1};
}

这让我感到困惑,因为我真的看不到任何可能有用的情况。您什么时候要为复合文字赋予 什么?

还是这是常见的未定义行为之一?因为它看起来非常像修改字符串文字。使用上面的相同参数编译时不会发出警告:

struct foo *ptr = &(struct foo){0,0};
*ptr = (struct foo){1,1};

char *str = "Hello";
*str = 'X'; // Undefined behavior

根据C standard 6.4.5.7

修改字符串是未定义的行为

解决方法

好吧,它可能不是有用,但它具有最低限制

由于非数组类型的非const限定复合文字是,因此可以在所有 中将可修改的lvalue分配给 到可修改的左值,那么您可以 分配给复合文字。

相反的是,对于复合文字的左值,您可能会遇到一些 extra 情况,因为您无法做到


我为此找到了一个用例,将工作分配给左值,而不会:

既然您刚才说过您不喜欢宏,那么我不确定这是否可以说服您,但是这使得编写一个扩展为类似宏的宏成为可能。
foo(&((struct baz){0} = bar()))

此处bar返回一个struct baz作为值,而foo需要一个指向该struct的指针作为参数。没有此功能,您将无法内联传递此类值。

,

复合文字的目标是什么?
目的是在堆栈上创建完全可用的而不提供名称。

“堆栈上完全可用的对象”是否必须是左值?
是。复合文字的典型用法之一是获取其地址并将其传递给某些函数。目的是,每当我有一个使用Foo* fooPtr的函数时,我都可以将参数作为复合文字&(Foo){...}提供。由于我要获取地址,并且需要将非常量指针传递给函数,因此复合文字必须为左值。

请注意,该函数然后可以使用简单的*fooPtr = (Foo){...};分配给对象。这样的代码对于构造函数或重置对象的函数非常典型。函数不知道fooPtr是否指向堆上的复合文字,命名变量或内存块。在所有这些情况下,转让都是合法的。

您看到,可以分配给复合文字的事实只是复合文字为左值的副作用。而且,如果复合文字确实是左值,则它们仅可用作内联的即时对象创建构造。

,

我找不到任何好的用处,但确实发现了字符串文字的一些显着差异。 chapter about compound literals仅出现“ undefined”一词,并且可以看到,它通常不适用于赋值或其他修改:

16请注意,如果使用迭代语句而不是显式的goto和带标签的语句,则未命名对象的生存期将仅是循环的主体,并且在下次进入p时将具有不确定的值,这将导致不确定的行为。

因此,“是否存在未定义的行为”的答案似乎是:“不,不是。”

此外,另一个区别是寿命。而字符串文字always have static storage的复合文字却没有:

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
}

我也做了一个实验。我百分百地解释它,因为它既可以解释为静态存储又可以定义为未定义的行为。输出为“ 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 的复合文字应指定 distinct 对象,但这不适用于字符串文字。

,

IMO即使没有用,也没有理由禁止它。

IMO非常类似于

void foo(void)
{
    int a = a;

    a = a;
}

即使a也被编译器视为已初始化:)

https://godbolt.org/z/Msv6q9

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?