2

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

  • 我一直认为限定符与有效类型并不真正相关,因为规则谈到左值访问,这意味着左值转换会丢弃限定符。但是如果对象是一个指针呢?指向数据的限定符不受左值转换的影响。

    Q1:如果有效类型是指向限定类型​​的指针怎么办?我可以将它作为指向同一类型的非限定指针进行左值访问吗?这在标准的什么地方有规定?

  • 在这些情况下,严格别名规则的例外情况会提到限定符:

    — 与对象的有效类型兼容的类型的限定版本,
    — 与对象的有效类型对应的有符号或无符号类型,
    — 与限定版本对应的有符号或无符号类型对象的有效类型,

    这些地址限定符都不是有效类型本身,只有用于访问的左值。由于左值转换,这应该是无关紧要的......对吗?

    Q2:左值转换是在上面引用的有效类型/严格别名规则应用之前还是之后发生的?

    Q3:有效类型是否带有限定符?这在标准的什么地方有规定?

4

1 回答 1

2

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

到目前为止提到的任何类型都是非限定类型。每个非限定类型都有其类型的多个限定版本,对应于 , 和 限定符中的一个、两个或所有三个constvolatile组合restrict。类型的合格或不合格版本是属于同一类型类别并具有相同表示和对齐要求的不同类型。派生类型不受其派生类型的限定符(如果有)限定。

(C17 6.2.5/26)

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

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

有了这样的背景,

Q1:如果有效类型是指向限定类型​​的指针怎么办?我可以将它作为指向同一类型的非限定指针进行左值访问吗?这在标准的什么地方有规定?

我认为你的意思是:

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

的有效类型xconst uint32_t *(指向const-qualified的非限定指针uint32_t),并且通过类型的左值uint32_t *(指向 unqualified 的非限定指针uint32_t)访问它。这种组合不在语言规范允许的例外之列。特别是,uint32_t *不是 a 的合格版本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 * const的合格版本const uint32_t *

Q2:左值转换是在上面引用的有效类型/严格别名规则应用之前还是之后发生的?

我看不出在严格别名之前如何解释左值转换。严格的别名规则以用于访问对象的左值表示,左值转换的结果不是左值。

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

Q3:有效类型是否带有限定符?这在标准的什么地方有规定?

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

于 2022-01-17T16:56:35.610 回答