c - 表达式中的严格别名

标签 c language-lawyer strict-aliasing

假设我们有以下代码:

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint16_t a[] = { 1, 2, 3, 4 };
    const size_t n = sizeof(a) / sizeof(uint16_t);
    
    for (size_t i = 0; i < n; i++) {
        uint16_t *b = (uint16_t *) ((uint8_t *) a + i * sizeof(uint16_t));
        printf("%u\n", *b);
    }
    
    return 0;
}
显然,类型转换auint8_t指针不是违规,所以这个问题是关于将结果指针转换为 uint16_t指针。根据我的理解,根据标准,它确实违反了严格的别名规则。但是,从实际的角度来看,我不确定,因为 a 的类型和 b是兼容的。唯一可能的违规行为是 b别名 uint8_t只存在于这个 one 表达式中的指针。所以在我的理解中,即使它违反了规则,我也会怀疑它会导致未定义的行为。它可以?
请注意,我并不是说这段代码是有意义的。这个问题纯粹是出于对严格别名的理解的教育目的。

最佳答案

这是不是 严格的别名违规。a的转换至 uint8_t并且后续的指针算术是安全的,因为转换为指向字符的指针类型会出现异常。
C standard 的第 6.3.2.3p7 节状态:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68)for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to theo riginal pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.


转换回和随后的取消引用是安全的,因为 b指向类型为 uint16_t 的对象(特别是数组 a 的成员),匹配 b 的指向类型.
第 6.5p7 节指出:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

  • a type compatible with the effective type of the object,
  • 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,
  • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
  • a character type.

关于c - 表达式中的严格别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66533019/

相关文章:

c++ - `std::complex<T>[n]` 和 `T[n*2]` 类型别名

c - 将指针写入管道,是否存在任何严格的别名或双关类型问题?

c++ - 为什么 param_type 构造函数对于随机分布是显式的?

c - 如何在 C 中对 argv 的元素进行排序?

c - 如何定义链表节点 "recursively"?

c - 为什么程序打印 0?

c - 试图从标准中理解有符号整数转换规则

c++ - 不正确的类型转换 - 类型转换或未定义行为的使用

c - 严格的别名和覆盖继承

c - 不明白 "....*(BYTE *)p=0xff;...."这样的一段代码