【问题标题】:Effective type of temporary object in CC中临时对象的有效类型
【发布时间】:2019-07-11 00:44:04
【问题描述】:

这是一个与C标准的defect report 452相关的问题。文档N1888 提供了有关原始问题的更多信息,但我不明白为什么它会说明以下内容:

6.5.p6 中的有效类型规则(描述什么是对象的有效类型的规则)似乎不适用于由逗号表达式产生的具有临时生命周期的对象。因此,它似乎没有有效的类型。 因此,类型双关语似乎是允许的

long func3() {
   union u2 o3 = { .x=42 };
   return (0, o3).y;
}

我的问题是,如果由表达式 (0, o3) 创建的具有临时生命周期的对象没有有效类型,是什么导致类型双关语合法?我相信只有在尝试使用不同类型访问其存储值时,该对象的有效类型才会相关,但我看不出这里是怎么回事。

【问题讨论】:

    标签: c language-lawyer type-punning


    【解决方案1】:

    我相信只有在尝试使用不同类型访问其存储值时,该对象的有效类型才会相关,但我不明白这里是怎么回事。

    但实际上该对象已尝试使用不同的类型访问其存储的值

    union u2 {
        int x;
        long y;
        char ca[2];
      };
    

    成员 xy 具有不同的类型(即使它们可能具有相同的表示形式)。

    但是当涉及到联合时,不能说我们正在通过另一个对象的类型访问一个对象(我知道对此存在一些争论,但标准中有一条注释允许通过联合进行类型双关;我知道注释不是规范性的,但我相信其目的是使其有效)。

    您似乎指的是标准中的这个注释

    1. 如果用于读取联合对象内容的成员与上次用于读取的成员不同 在对象中存储一个值,该值的对象表示的适当部分被重新解释 作为 6.2.6 中描述的新类型中的对象表示(有时称为“类型 双关语'')。这可能是一个陷阱表示。

    您需要定义 valid 的含义,但根据上述,它不能表示“标准定义的保证行为”,因为它可能导致“陷阱表示” “, 一世。 e.读取时未定义的行为。

    【讨论】:

    • 从标准的角度来看,我认为非左值表达式的值不会存储在任何地方,因此我认为它们不会被“访问”。当然对于像unsigned 这样的类型,在评估w=x*y+x*z; 期间,值x*y 是从某个地方“读取”的,这似乎很奇怪,特别是因为实现可能根本不需要计算该值,而是计算x*(y+z) [无符号算术表现为代数环,因此这样的转换是合法的]。
    • 唯一真正奇怪的情况是结构或联合类型的值包含数组时。我认为标准应该在结构或联合类型的非左值值中包含的数组上定义[] 的行为,但禁止此类数组衰减,但现在这样做将是一个重大变化。
    • @Armali 感谢您的回复。但是当谈到联合时,不能说我们正在通过另一个对象的类型访问一个对象(我知道对此存在一些争论,但标准中有一条注释允许通过联合进行类型双关;我知道注释不是规范,但我相信其目的是使其有效)。
    • 我对此进行了更多思考,并与其他人进行了交谈,原因是@supercat 所述。例如,如果一个结构的第一个成员具有数组类型,而函数f 返回此类型的对象,则编写类似&f().arr[0] 的内容(其中arr 是具有数组类型的结构成员) 允许我们获取“具有临时生命周期的对象”(结构对象)的地址。在该缺陷报告之前,此类对象没有有效的类型,因此无论其他什么类型都可以访问它们。
    • @user42768:如果标准已经认识到a[b] 仅在操作数是指针和整数(以任意顺序)的情况下等同于*(a+b),则可以避免很多混淆, 并将[] 应用于数组类型的值或左值会产生标识该数组的相应元素的元素类型的值或左值,或者“刚刚过去”数组的空左值。这将消除对寄存器限定数组应该意味着什么的混淆,并且还使得实现支持位域数组成为可能,因为这样做会很有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2020-10-07
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    相关资源
    最近更新 更多