c - 有效类型限定符有哪些规则?

标签 c language-lawyer lvalue strict-aliasing c17

所以我正在重新阅读 C17 6.5/6 - 6.5/7 关于有效类型和严格别名的内容,但不知道如何处理限定符。有些事情让我困惑:

  • 我始终认为限定符与有效类型并不真正相关,因为规则涉及左值访问,这意味着丢弃限定符的左值转换。但如果对象是指针怎么办?指向数据的限定符不受左值转换的影响。

    问题1:如果有效类型是指向限定类型​​的指针怎么办?我可以左值将其作为指向同一类型的非限定指针来访问吗?标准中哪里有这样的规定?

  • 严格别名规则的异常(exception)在这些情况下提及限定符:

    — a qualified version of a type compatible with the effective type of the object,
    — a type that is the signed or unsigned type corresponding to the effective type of the object,
    — a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

    这些地址限定符都不是有效类型本身,只能通过左值进行访问。这应该是完全不相关的,因为左值转换......对吗?

    问题2:左值转换是在应用上述有效类型/严格别名规则之前还是之后发生?

    Q3:有效类型是否带有限定符?标准中哪里有这样的规定?

最佳答案

“限定类型”是一个已定义的术语,该定义可能相关:

Any type so far mentioned is an unqualified type. Each unqualified type has several qualified versions of its type, corresponding to the combinations of one, two, or all three of the const, volatile, and restrict qualifiers. The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements. A derived type is not qualified by the qualifiers (if any) of the type from which it is derived.

(C17 6.2.5/26)

我注意到 _Atomic 关键字与其他三个分类为类型限定符的关键字不同,我认为这与原子类型不需要具有相同的表示或对齐方式有关需求作为其对应的非原子类型。

我还注意到,规范明确指出类型的限定版本和非限定版本是不同的类型。

有了这样的背景,

Q1: What if the effective type is a pointer to qualified-type? Can I lvalue access it as a non-qualified pointer to the same type? Where in the standard is this stated?

我认为你的意思是这样的:

const uint32_t *x = &some_uint32;
uint32_t * y = *(uint32_t **) &x;

x 的有效类型是 const uint32_t *(指向 const 限定的 uint32_t 的非限定指针) ,并且它是通过 uint32_t * 类型的左值(指向非限定 uint32_t 的非限定指针)访问的。这种组合不属于语言规范允许的异常(exception)情况。特别是,uint32_t * 不是 const uint32_t * 的限定版本。因此,正如 C17 6.5 第 6 和 7 段中所规定的,结果行为是未定义的。

虽然该标准没有讨论 SAR 的这种特殊应用,但我认为它是间接合理的。在这种情况下,问题不在于访问指针值本身,而在于生成一个其类型丢弃所指向类型的限定符的指针。

另请注意,SAR 确实允许这种变化:

const uint32_t *x = &some_uint32;
const uint32_t * const y = *(const uint32_t * const *) &x;

,因为 const uint32_t * constconst uint32_t * 的限定版本。

Q2: Does lvalue conversion happen before or after the above quoted rules of effective type/strict aliasing are applied?

我不明白如何将左值转换解释为在严格别名之前应用。严格的别名规则以用于访问对象的左值来表示,并且左值转换的结果不是左值。

此外,正如 @EricPostpischil 所观察到的,SAR 适用于所有访问,包括写入。对于正在写入的左值,首先没有左值转换。

Q3: Does the effective type come with qualifiers or not? Where in the standard is this stated?

类型的限定版本和非限定版本是不同的类型。我认为没有理由解释第 6.5/6 段的“对象的声明类型”或“左值的类型”,就好像该类型应该被视为删除了其限定符,更不用说好像该类型中的所有限定符一样它的来源已被剥离。 “类型”一词就是他们所说的意思。

关于c - 有效类型限定符有哪些规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65356861/

相关文章:

c - "__G"是什么意思?

c - static 和 set_global 一起 : how come?

c++ - 符合标准的 C++ 实现如何表明它不知道当前日期和时间?

c++ - 为什么左值转换有效?

c++ - C++ const 引用和 const 之间的区别?

C 在 execvp 中传递一个参数和两个参数

c - strcpy函数: C

c++ - 没有 <> 的模板特化

c - 流错误指示器如何影响以下输入代码?

c++ - MSVC++ 使用基本运算符 = 重载左值而不是右值?