概述
- 1. MSB、LSB
- 2. 最高有效字节、最低有效字节
- 3. 大小端
- 4. 如何判断本机大小端
- 5. 大小端转换
1. MSB、LSB
以整数“157”为例
MSB :单个字节中的最高位 2^7 = 128
LSB :单个字节中的最低位 2^0 = 0
2. 最高有效字节、最低有效字节
以整形“0x01020304”为例
最高有效字节:0x01
最低有效字节: 0x04
3. 大小端
在计算机科学中,大小端(Endian)是一个术语,用于描述多字节数据在内存中的存储顺序。具体地说,它指的是一个数据单元(如整数、浮点数等)的字节(而非位)如何在内存地址中排列。这个术语来源于“Endian”一词,它源自于乔纳森·斯威夫特的小说《格列佛游记》中的一个小岛,岛上的居民在争论吃鸡蛋时应该从大头(Big-End)开始还是从小头(Little-End)开始,这反映了一种在细节上争执不下的文化。
大端(Big-Endian)
在大端字节序中,数据的最高有效字节存储在内存的低地址端,而最低有效字节存储在内存的高地址端。
小端(Little-Endian)
在小端字节序中,数据的最低有效字节存储在内存的低地址端,而最高有效字节存储在内存的高地址端。
以整形“0x01020304”为例
大端模式 : 0x01 0x02 0x03 0x04
小端模式 : 0x04 0x03 0x02 0x01
4. 如何判断本机大小端
#include <iostream>
// 函数用于判断本机的大小端模式
bool isLittleEndian() {
// 定义一个联合体,包含一个整型和一个字符数组
union {
uint32_t i;
char c[4];
} test;
// 给整型赋值,这里使用了一个十六进制数,方便查看其在内存中的存储方式
test.i = 0x01020304;
// 检查字符数组的第一个字节
// 如果是小端模式,低地址处存储的是低位字节,即0x04
// 如果是大端模式,低地址处存储的是高位字节,即0x01
return static_cast<char>(0x04) == test.c[0]; // 注意这里直接比较的是字符的ASCII值,'4'的ASCII值是52,但这里我们实际上是在比较整数值4
}
int main() {
if (isLittleEndian()) {
std::cout << "This machine is little endian." << std::endl;
} else {
std::cout << "This machine is big endian." << std::endl;
}
return 0;
}
5. 大小端转换
#include <iostream>
// 大小端类型
enum EndianType{
eEndianLittle,
eEndianBig
};
// 函数用于判断本机的大小端模式
bool isLittleEndian() {
union {
uint32_t i;
char c[4];
} test;
test.i = 0x01020304;
return test.c[0] == 4;
}
// 返回本机大小端
const EndianType& LocalEndianType()
{
static EndianType type = isLittleEndian() ? eEndianLittle : eEndianBig;
return type;
}
// 转换大小端
using Byte = unsigned char;
void toEndian(const EndianType& type, Byte* begin, int size)
{
if (size > 1 && LocalEndianType()!=type)
{
Byte* beg = begin, *end = begin + size - 1;
while(beg < end)
{
std::swap(*beg++,*end--);
}
}
}
int main()
{
union {
uint32_t i;
unsigned char sz[4];
} test;
test.i = 0x01020304;
std::cout << (int)test.sz[0] << std::endl;
toEndian(eEndianBig, test.sz, 4);
std::cout << (int)test.sz[0] << std::endl;
}