C筆試題之編程題一


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 格式控制符。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM