最轻量常用方法是union检测:写入0x01020304后读bytes[0],值为0x04则小端,0x01则大端;C++20可用std::endian编译期判断;指针转换有未定义行为风险;宏定义仅反映编译目标,非运行时真实序。
最轻量、最常用的方法是定义一个 union,把整数和字节数组共用同一块内存,然后写入一个非对称值(如 0x01020304),再读取第一个字节判断高低位分布。
0x01020304 在内存中低地址存 0x04,所以 bytes[0] 为 0x04
bytes[0] 为 0x01
union EndianTest {
uint32_t value;
uint8_t bytes[4];
};
EndianTest test;
test.value = 0x01020304;
if (test.bytes[0] == 0x04) {
// 小端
} else if (test.bytes[0] == 0x01) {
// 大端
}
std::endian(C++20)直接查标准枚举C++20 引入了 std::endian 枚举,在编译期就能确定字节序,无需运行时检测,且可配合 if constexpr 做零开销分支。
std::endian::little 表示小端,std::endian::big 表示大端std::endian::native 是当前平台实际字节序,多数情况等于前两者之一__cpp_lib_endian 宏#include#if __cpp_lib_endian >= 201907L if constexpr (std::endian::native == std::endian::little) { // 编译期已知小端 } #endif
有人会写 *reinterpret_cast 取首字节,这在绝大多数编译器上能工作,但严格来说违反 C++ 严格别名规则(strict aliasing),可能被优化掉或触发未定义行为。
-O2 下可能把这类读取优化成常量,导致误判volatile 或 memcpy 绕过别名限制union 方案,它没有语言标准背书,可移植性差像 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 这类宏,是编译器根据目标平台设定的,一般可靠,但要注意:
真正关键的不
