首先需要一些概念:
对于一个 ω \omega ω位的整数,其位表示为[x ω \omega ω-1, x ω \omega ω-2, …, x2, x1]。其中:
为方便记忆,可以将大端法类比为日常手写数字的顺序,左侧(内存中的低地址)是数字高位有效数字,右侧是低位数字。
以32位int整数0x12345678
为例,该int位于内存的地址位0x100
,则两种情况的内存分布为:
4004d3: 01 05 43 0b 20 00 add %eax,0x200b43(%rip)
已知上述代码设计两个数相加:PC寄存器中的值和0x200b43
。0x200b43这个值位于指令的最后四个字节:43 0b 20 00, 根据小端存储的定义并去掉第一个符号位字节,该数值即为20 0b 43
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i = 0; i < len; ++i) {
printf(" %.2x", start[i]);
}
printf("\n");
}
// 使用sizeof并用size_t类型接受,从而不受编译环境的影响·
void show_int(int x) {
show_bytes((byte_pointer)&x, sizeof(int));
}
void show_float(float x) {
show_bytes((byte_pointer)&x, sizeof(float));
}
void show_void(void *x) {
show_bytes((byte_pointer)&x, sizeof(void *));
}
void test_show_bytes(int val) {
int ival = val;
float fval = (float) ival;
int *pval = &ival;
show_int(ival);
show_float(fval);
show_void(pval);
}
int main()
{
test_show_bytes(12345);
return 0;
}
以下是在Linux 32bit和Linux 64bit测试结果:
## linux 32
39 30 00 00
00 e4 40 46
04 79 84 bf
## linux 64
39 30 00 00
00 e4 40 46
a8 72 70 39 fd 7f 00 00
0x00003039
, 上述机器均为小端存储。还有其他的巧妙测试方法:
#include <iostream>
using namespace std;
int main()
{
int a = 0x1234;
//由于int和char的长度不同,借助int型转换成char型,只会留下低地址的部分
char c = (char)(a);
if (c == 0x12)
cout << "big endian" << endl;
else if(c == 0x34)
cout << "little endian" << endl;
}
#include <iostream>
using namespace std;
//union联合体的重叠式存储,endian联合体占用内存的空间为每个成员字节长度的最大值
union endian
{
int a;
char ch;
};
int main()
{
endian value;
value.a = 0x1234;
//a和ch共用4字节的内存空间
if (value.ch == 0x12)
cout << "big endian"<<endl;
else if (value.ch == 0x34)
cout << "little endian"<<endl;
}
上述两种方法参考来源:阿秀的校招笔记