轉自http://blog.csdn.net/delphiwcdj/article/details/6234383
問題 :如何用程序確認當前系統的存儲模式(大端還是小端)?寫一個C函數,若處理器是Big-endian的,則返回0;若是Little-endian的,則返回1。
情況1:利用數組類型
- #include <cstdio>
- int checkSystem()
- {
- char s[]="1000";
- return (s[0]=='1');
- }
- int main()
- {
- checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n");
- return 0;
- }
情況2:利用位移運算
- int i = 1;
- if(1>>32 == 0)
- cout<<"小端模式"<<endl;
- else
- cout<<" 大端模式"<<endl;
上述方法正確嗎?要理解為什么不正確?
因為不要在數值上做文章,而大小端是嚴格與內存掛鈎的東西。如果int a=1; 那么a&1==1一定成立,因為這是從數值角度運算的,已經給用戶屏蔽掉了大小端的問題。一定要int a=1; *((char*)(&a)) == 1 ,這樣判斷才有效。
下面總結一些有效的方法。
方法1:利用union類型 —— 可以利用union類型數據的特點:所有成員的起始地址一致。
- #include <cstdio>
- int checkSystem()
- {
- union check
- {
- int i;
- char ch;
- }c;
- c.i=1;
- return (c.ch==1);
- }
- int main()
- {
- checkSystem()==1 ? printf("Little-endian/n") : printf("Big-endian/n");
- return 0;
- }
方法2:對int強制類型轉換
- #include<stdio.h>
- #include<stdlib.h>
- int main()
- {
- int i = 1;
- (*(char *)&i == 1) ? printf("Little-endian/n") : printf("Big-endian/n");
- system("pause");
- return 0;
- }
方法3:使用union和宏定義
- #include<stdio.h>
- #include<stdlib.h>
- static union
- {
- char a[4];
- unsigned long ul;
- }endian = {{'L', '?', '?', 'B'}};
- #define ENDIAN ((char)endian.ul)
- int main()
- {
- printf("%c/n", ENDIAN);
- system("pause");
- return 0;
- }
補充:
大小端模式對union類型數據的影響。
- #include <cstdio>
- union
- {
- int i;
- char a[2];
- }*p, u;
- int main()
- {
- p=&u;
- p->a[0]=0x39;
- p->a[1]=0x38;
- printf("%x/n",p->i);// 3839 (hex.)
- printf("%d/n",p->i);// 111000 00111001=14393 (decimal)
- return 0;
- }
分析如下圖所示:
高地址 低地址
—— —— —— —— int
0 | 0 | 56 | 57
—— —— —— ——
—— —— char
56 | 57
—— ——
這里需要考慮存儲模式:大端模式和小端模式。
大端模式(Big-endian):數據的低字節存放在高地址中。
小端模式(Little-endian):數據的低字節存放在低地址中。
union型數據所占的空間等於其最大的成員所占的空間,對union型成員的存取都是相對於該聯合體基地址的偏移量為0處開始,即,聯合體的訪問不論對哪個變量的存取都是從union的首地址位置開始。因此,上面程序輸出的結果就顯而易見了。