2024-04-15 11:19:57 +08:00
|
|
|
|
---
|
|
|
|
|
title: 大端小端
|
|
|
|
|
updated: 2022-05-16 09:21:27Z
|
|
|
|
|
created: 2022-01-14 00:12:17Z
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# 含义
|
|
|
|
|
大端(big endlian)和小端(little endian)属于字节序。 [位序](位序.md)
|
|
|
|
|
> 只有读取的时候,才必须区分字节序,其它情况都不用考虑//==有待验证==
|
|
|
|
|
|
|
|
|
|
内存地址由低到高,从左往右,与人类阅读顺序一致。
|
|
|
|
|
## 理解
|
|
|
|
|
在几乎所有的机器上,多字节对象都被存储为连续的字节序列,并从地址位开始存储。==先存储多字节数据的低位即为小端(small),先存储高位即为大端(big)==。
|
|
|
|
|
## 大端字节序:
|
|
|
|
|
认为第一个内存地址字节是数据为最高位字节,即大端即高字节存在低地址位,低字节存在高地位,故==在从左往右的阅读习惯下,数据视觉上是一致的==,即存储后的字面数据值与实际数据一致。
|
|
|
|
|
0xABCDEF在内存中即为0xAB|0xCD|0xEF
|
|
|
|
|
## 小端字节序:
|
|
|
|
|
认为第一个字节存储低位,如此内存中数据字面数值与实际数值相反。
|
|
|
|
|
故在从左往右的阅读习惯下,数据视觉上是==相反的==。
|
|
|
|
|
0xABCDEF在内存中即为0xEF|0xCD|0xAB
|
|
|
|
|
# 场景
|
|
|
|
|
x86等多是小端
|
2024-12-31 10:10:16 +08:00
|
|
|
|
ARM等为可配置,一般默认为小端
|
|
|
|
|
|
|
|
|
|
# 判断、转换
|
|
|
|
|
```c
|
|
|
|
|
// 判断系统大端序还是小端序
|
|
|
|
|
|
|
|
|
|
static uint8_t IsBigEndian() {
|
|
|
|
|
uint32_t num = 0x12345678;
|
|
|
|
|
return ((*(uint8_t*)&num) == 0x12);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将数据按大端序填充
|
|
|
|
|
|
|
|
|
|
static void FillBigEndian32(uint8_t *data, uint32_t value) {
|
|
|
|
|
if(!IsBigEndian()) {
|
|
|
|
|
for(uint16_t i = 0; i < 4; i++) {
|
|
|
|
|
data[i] = (value >> ((4 - i - 1) * 8)) & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for(uint16_t i = 0; i < 4; i++) {
|
|
|
|
|
data[i] = (value >> (i * 8)) & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void FillBigEndian16(uint8_t *data, uint16_t value) {
|
|
|
|
|
if(!IsBigEndian()) {
|
|
|
|
|
for(uint16_t i = 0; i < 2; i++) {
|
|
|
|
|
data[i] = (value >> ((2 - i - 1) * 8)) & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
for(uint16_t i = 0; i < 2; i++) {
|
|
|
|
|
data[i] = (value >> (i * 8)) & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
2024-04-15 11:19:57 +08:00
|
|
|
|
|