当前位置: 首页 > 知识库问答 >
问题:

从函数和未定义的行为返回局部部分初始化的结构

姜磊
2023-03-14

使用可以用register定义的自动未初始化变量,因为rvalue是未定义的行为。可以使用寄存器存储类说明符定义结构。

6.3.2.1

请注意,它特别指出,并且没有对它执行任何赋值。

struct test
{
    int a;
    int b;
};

struct test Get( void )
{
    struct test g;
    g.a = 123;
    return g;
}

{
    struct test t = Get();
}

我的说法正确吗?

共有1个答案

柴凌
2023-03-14

除了从函数返回值的细节之外,这恰恰是Clive Feather于2000年提交的缺陷报告222的主题,该DR的解决方案似乎非常清楚地回答了这个问题:返回部分未初始化的结构是定义良好的(尽管未初始化成员的值可能不会被使用)

对DR的决议澄清了structunion对象不具有陷阱表示形式(这被明确添加到§6.2.6.1/6)。因此,不能在单个成员可能陷入的体系结构上使用逐个成员的复制。虽然可能是为了简洁起见,标准中没有增加这方面的明确说明,但先前提到逐个成员复制可能性的脚注42(现为脚注51)被一个弱得多的说明取代,说明不需要复制填充位。

第14工作组会议(2000年10月,多伦多)的记录很清楚(着重部分是后加的):

DR222-部分初始化的结构

当赋值的源是struct(其某些成员未被赋予值)时,这个DR会询问struct赋值是否定义良好。由于常见的用法,包括标准指定的结构structtm,因此大家一致认为应该对其进行很好的定义。还有一个共识是,如果对某些成员的赋值未初始化(因此可能具有陷阱值)进行了良好定义,那么要求至少一个成员正确地给定了一个值就没有什么价值了。
因此,将结构联合的值作为一个整体可以具有陷阱值的概念正在被删除。

有趣的是,在上述会议记录中,委员会认为,甚至没有必要为struct的单个成员赋予一个值。然而,后来在某些情况下恢复了这一要求,决议为DR338(见下文)。

这样的对象可以分配给另一个相同类型的聚合对象,可能是在从函数返回之后,而不需要调用未定义的行为。

读取副本中的未初始化成员要么是未定义的,要么是不确定的,这取决于陷阱表示形式是否可能。(例如,通过指向无符号窄字符类型的指针读取无法捕获。)但如果你在阅读之前写了成员,你就没事了。

我不认为unionstruct对象的赋值在理论上有任何区别。很明显,union不能逐个成员复制(这意味着什么),而且某些非活动成员碰巧具有陷阱表示形式这一事实与此无关,即使该成员没有被任何其他元素别名。struct没有明显的不同的原因。

 类似资料:
  • 下面的代码在clang中可以工作,但是在g中会崩溃 罪魁祸首原来是这句台词: 在clang中,在之前评估,在g中相反,导致迭代器在被取消引用之前被增加。事实证明,评估函数参数的顺序是由实现定义的。 我的问题是:我如何捕捉这种类型的错误?理想情况下,当我意外地依赖于特定的实现细节时,我希望有一个错误或至少一个警告。 即使使用-Wall,clang和gcc也不会产生任何警告。

  • 问题内容: 在Java中,但是在其他OO语言中,初始化属性定义之间也有区别,例如 并使用构造函数对其进行初始化? 我想不出任何实际的区别,有没有?否则,即使结果相同,是否存在一种方法优于另一种方法的情况? 问题答案: 初始化顺序在这里很重要。 将字段设置为默认初始值(0,false,null) 调用对象的构造函数(但不要执行构造函数的主体) 调用超类的构造函数 使用初始化程序和初始化块初始化字段

  • 问题内容: 我正在读一本叫做《 Go编程语言》的书,在有关指针的第二章中,写了以下内容 函数返回局部变量的地址是绝对安全的。例如,在下面的代码中,即使调用返回后,由对f的特定调用创建的局部变量v仍将存在,并且指针p仍将引用它: 我完全不明白这一点,应该在执行函数后销毁局部变量。是因为可能v是在堆上分配的。我知道在C语言中,如果您使用malloc分配空间,函数执行后就不会销毁它,因为它在堆上。 问题

  • 因此,我有一个链接到Firebase项目的GCP项目(因此,我可以使用Cloud FiRecovery而不是Datastore)。 我用Python编写了一个云函数,在尝试通过以下方式部署它时: 这需要很长时间,然后会出现以下错误: 错误:(gcloud.functions.deploy)操作错误:代码=13,消息=初始化区域失败(操作ID:c6a9e29e404f3d1e) 如果我在任何其他没有

  • 我对python相当陌生,我想知道局部变量是如何工作的。让我们从一个简单方法的示例开始: 让我们假设local_dict像一种常量变量一样使用。这里有一个问题:它是在每次调用do_sth()时创建的,还是创建一次并保存在do_sth()内部的某个地方?