1、編寫一個簡單函數檢查處理器是 big-endian 還是 little-endian。
定義:
little-endian 就是低位字節排放在內存的低地址端,高位字節排放在內存的高地址端;
big-endian 就是高位字節排放在內存的低地址端,低位字節排放在內存的高地址端;
網絡字節序 TCP/IP各層協議將字節序定義為Big-Endian,因此TCP/IP協議中使用的字節序通常稱之為網絡字節序。
思路:
由於聯合體union的存放順序是所有成員都從低地址開始存放,利用該特性就可以輕松地獲得了CPU對內存采用Little- endian還是Big-endian模式讀寫。
1 #include <stdio.h>
2
3 int main(void) 4 { 5 union MyUnion 6 { 7 unsigned int a; 8 unsigned char b; 9 }; 10
11 union MyUnion test; 12 test.a = 1; 13 printf("%d\n", test.b);//1:little-endian 0:big-endian
14
15 return 0; 16 }
如上圖,我的處理器是 little-endian。
2、假設 x = 9999,求下面函數的返回值。—— 微軟
1 int func(x) 2 { 3 int countx =0; 4 while (x) 5 { 6 countx++; 7 x = x & (x - 1); 8 } 9 return countx; 10 }
思路:將 x 轉換為二進制表示,看其中1的個數。如 x = 9999 = 0B0010 0111 0000 1111(對於二進制數前綴0B,有的編譯器可能會出錯),其中有8個1,則函數返回值 countx=8。
原理:每執行一次 x = x & (x - 1),會將 x 用二進制表示時最右邊的一個1變為0,因為 x - 1 將會將該位(x用二進制表示時最右邊的一個1)變為0。
1 #include <stdio.h> 2 3 int func(int x); 4 5 int main(void) 6 { 7 int x; 8 9 printf("please enter a integer(>0):"); 10 if ((1 == (scanf("%d", &x))) && (x > 0)) 11 printf("%d\n",func(x)); 12 else 13 printf("please enter a integer(>0)\n"); 14 15 return 0; 16 } 17 18 int func(int x) 19 { 20 int countx = 0; 21 while (x) 22 { 23 countx++; 24 x = x & (x - 1); 25 } 26 return countx; 27 }
驗證代碼如上,如鍵入9999,結果如下:
3、請編寫一個簡單的函數判斷一個數是否是2的n次方。
思路:如果一個整數是2的n次方,那么這個數用二進制表示時其最高位為1,其余位為0。此題轉變為判斷一個整數用二進制數表示時最高位是否為1,用 (x = x & (x - 1)) == 0可判斷,此題與例2均為巧用 x = x & (x - 1)。
1 #include <stdio.h> 2 3 void func(int x); 4 5 int main(void) 6 { 7 int x; 8 9 printf("please enter a integer(>=0):"); 10 if (1 == scanf("%d", &x)) 11 func(x); 12 else 13 printf("please ensure it's a integer.\n"); 14 15 return 0; 16 } 17 18 void func(int x) 19 { 20 if (0 == (x = x & (x - 1))) 21 printf("Yes.\n"); 22 else 23 printf("No.\n"); 24 }
4、下面關於“聯合”的程序的輸出是什么?
1 #include <stdio.h> 2 3 union 4 { 5 int i; 6 char x[2]; 7 }a; 8 9 void main(void) 10 { 11 a.x[0] = 10; 12 a.x[1] = 1; 13 printf("%d\n", a.i); 14 }
思路:整型變量 i 和 char 型數組共享一個內存地址。值以數組形式存入,以整型變量讀出。
注意:x[0]內存低地址,x[1]內存高地址。當處理器為 little-endian 時,以整型變量讀出為 0X010A;當處理器為 big-endian 時,以整型變量讀出為 0X0A01。
我的PC處理器為 little-endian ,所以程序輸出為 0X010A,即266。
5、下面關於“聯合”的程序的輸出是什么?
1 #include <stdio.h> 2 3 int main(void) 4 { 5 union 6 { 7 int i; 8 struct 9 { 10 char first; 11 char second; 12 }half; 13 }number; 14 15 number.i = 0x4241; 16 printf("%c%c\n", number.half.first, number.half.second); 17 18 number.half.first = 'a'; 19 number.half.second = 'b'; 20 printf("%x\n", number.i); 21 22 return 0; 23 }
思路:1、聯合體中各成員共享一塊內存(內存地址相同),故整型變量 i 與結構體 half 內存地址相同;
2、程序中動態變量存放在棧中,先定義先分配內存。對於單字節數據,很好理解;對於多字節數據,存在處理器是 big-endian 還是 little-endian 的問題。big-endian 的處理器存儲時將多字節的高位放在低地址,低位放在高地址,讀出時也將低地址的字節認為是高位,高地址的字節認為是高位;little-endian 的處理器存儲時將多字節的高位放在高地址,低位放在低地址,讀出時將低地址的字節認為是低位,高地址的字節認為是高位。
3、我的PC處理器是 little-endian,故四字節 i 的高位放置在高地址、低位放置在低地址,number.half.first 對應 i 的低地址,number.half.second 對應 i 的次低地址。
number.i = 0x4241,則 number.half.first = 0x41 = 'A' ; number.half.second = 0x42 = 'B' ; printf語句打印出 AB
number.half.first = 'a', number.half.second = 'b', 則 i 的低地址存儲 ‘a’ = 97 = 0x61, i 的次低地址存儲 'b' = 98 = 0x62; i 的高位及次高位為 0x0000; printf 語句打印出6261,需要打印出 0x 則需要使用 %#x 格式控制符。