是否将整数视为较小整数 UB 的数组?
比如这段代码中有没有UB:
#include <iostream>
#include <cstdint>
#include <algorithm> // sort
void sort_bytes(std::uint32_t& x) {
std::uint8_t* p = (std::uint8_t*)&x;
std::sort(p, p+4);
}
void sort_words(std::uint32_t& x) {
std::uint16_t* p = (std::uint16_t*)&x;
std::sort(p, p+2);
}
int main() {
const std::uint32_t x = 1234342542u;
std::uint32_t y = x, z = x;
std::cout << x << std::endl;
sort_bytes(y);
std::cout << y << std::endl;
sort_words(z);
std::cout << z << std::endl;
}
是的,这正是“严格别名规则”所禁止的。但是,编译器通常可以选择禁用对此规则的依赖,例如-fno-strict-aliasing
适用于 GCC 和 Clang,将在这些编译器的实际意义上定义行为。否则这些编译器会以意想不到的方式编译它,因为别名规则被破坏,导致 UB。
sort_bytes
可能是一个例外。 uint8_t
通常是
unsigned char
。 unsigned char
特别是别名规则有一个例外,并且可以为任何其他类型别名(但反之则不然)。因此从这个角度来看sort_bytes
没问题。但是,究竟要读取什么值是实现定义的,并且取决于所涉及类型的表示。在实践中,系统是小端还是大端(或者完全是其他系统)尤其重要。
但是,即使存在别名异常,目前的技术标准也不允许将强制转换的结果视为指向数组。然而,这可能是一个最终会得到解决的缺陷。