“合格类型”是一个定义的术语,该定义可能相关:
到目前为止提到的任何类型都是非限定类型。每个非限定类型都有其类型的多个限定版本,对应于 , 和 限定符中的一个、两个或所有三个const
的volatile
组合restrict
。类型的合格或不合格版本是属于同一类型类别并具有相同表示和对齐要求的不同类型。派生类型不受其派生类型的限定符(如果有)限定。
(C17 6.2.5/26)
我注意到_Atomic
关键字与其他三个归类为类型限定符的关键字不同,我认为这与原子类型不需要与其对应的非原子类型具有相同的表示或对齐要求这一事实有关。
我还注意到规范明确指出类型的合格和非合格版本是不同的类型。
有了这样的背景,
Q1:如果有效类型是指向限定类型的指针怎么办?我可以将它作为指向同一类型的非限定指针进行左值访问吗?这在标准的什么地方有规定?
我认为你的意思是:
const uint32_t *x = &some_uint32;
uint32_t * y = *(uint32_t **) &x;
的有效类型x
是const 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) 它的来源被剥离。“类型”一词的意思是他们所说的。