何为大小端?
大端模式:字数据的高字节存放在低地址中,而字数据的低字节则存放在高地址中。(低地址存放最高有效字节MSB)
小端模式:与大端存储格式相反,低地址中存放的是字数据的低字节,高地址中存放的是字数据的高字节。(低地址存放最低有效字节LSB)
使用C语言程序判断CPU大小端的方法:
NO1:直接使用看变量的内存值,这里需要一些调试技巧
1 #include<stdio.h>
2 void main()
3 {
4 short s=0x1234;
5 char * pTest=(char*)&s;
6 printf("%p %0X %X",&s,pTest[0],pTest[1]);
7 }
以十六进制输出short型变量s在内存中分字节分布。
运行结果为:
0012FF7C
34 12
NO2:使用C中的共用体union类型:可以利用union类型数据的特点——所有成员的起始地址一致。
写一个C函数,若处理器是Big_endian的,则返回false;若是Little_endian的,则返回true。
1 bool IsLitte_Endian()
2 {
3 union w{
4 int a;
5 char b;
6 }c;
7 c.a=1;
8 return (c.b==1);
9 }
1 #include <cstdio> 2 int checkSystem() 3 { 4 union check 5 { 6 int i; 7 char ch; 8 }c; 9 c.i=1; 10 return (c.ch==1); 11 } 12 int main() 13 { 14 checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n"); 15 return 0; 16 }
NO3:强制类型转换,和共用体的做法差不多
1 bool IsLitte_Endian()
2 {
3 int wTest = 0x12345678;
4 short *pTest=(short*)&wTest;
5 return !(0x1234 == pTest[0]);
6 }
补充:对int强制类型转换
1 #include<stdio.h>
2 #include<stdlib.h>
3 int main()
4 {
5 int i = 1;
6 (*(char *)&i == 1) ? printf("Little-endian/n") : printf("Big-endian/n");
7 system("pause");
8 return 0;
9 }
NO4:使用union和宏定义
1 #include<stdio.h>
2 #include<stdlib.h>
3 static union
4 {
5 char a[4];
6 unsigned long ul;
7 }endian = {{'L', '?', '?', 'B'}};
8 #define ENDIAN ((char)endian.ul)
9
10 int main()
11 {
12 printf("%c/n", ENDIAN);
13 system("pause");
14 return 0;
15 }
补充:大小端模式对union类型数据的影响
1 #include <cstdio>
2 union
3 {
4 int i;
5 char a[2];
6 }*p, u;
7 int main()
8 {
9 p=&u;
10 p->a[0]=0x39;
11 p->a[1]=0x38;
12 printf("%x/n",p->i);// 3839 (hex.)
13 printf("%d/n",p->i);// 111000 00111001=14393 (decimal)
14 return 0;
15 }
分析如下图所示:
高地址 低地址
—— —— —— —— int
0 | 0 | 56 | 57
—— —— —— ——
—— —— char
56 | 57
—— ——
这里需要考虑存储模式:大端模式和小端模式。
大端模式(Big-endian):数据的低字节存放在高地址中。
小端模式(Little-endian):数据的低字节存放在低地址中。
union型数据所占的空间等于其最大的成员所占的空间,对union型成员的存取都是相对于该联合体基地址的偏移量为0处开始,即,联合体的访问不论对哪个变量的存取都是从union的首地址位置开始。因此,上面程序输出的结果就显而易见了。