1. 程式人生 > >一些有趣的C語言題目

一些有趣的C語言題目

問題2:寫一個“標準”巨集,這個巨集輸入兩個引數並返回較小的一個

答:#define MIN(x,y)((x)<(y)?(x):( y))//結尾沒有; (注意幾個括號)

問題3:#與##的作用?

答:#是把巨集引數轉化為字串的運算子,##是把兩個巨集引數連線的運算子。

例如:

#define STR(arg)#arg則巨集STR(你好)展開時為“你好”

#define NAME(y)name_y則巨集NAME(1)展開時仍為name_y

#define NAME(y)name _ ## y則巨集NAME(1)展開為name_1

#define DECLARE(name,type)typename ## _ ## type ## _ type,

則巨集巨集DECLARE(val,int)展開為int val_int_type

15 Typedef在C語言中頻繁用以宣告一個已經存在的資料型別的同義字。也可以用前處理器做類似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上兩種情況的意圖都是要定義dPS和tPS作為一個指向結構s指標。哪種方法更好呢?(如果有的話)為什麼?
這是一個非常微妙的問題,任何人答對這個問題(正當的原因)是應當被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2; // p1為結構體指標   p2為結構體
tPS p3,p4;

// p3 p4為結構體指標
第一個擴充套件為
struct s * p1,p2;
上面的程式碼定義p1為一個指向結構的指,p2為一個實際的結構,這也許不是你想要的。第二個例子正確地定義了p3和p4兩個指標。晦澀的語法

問題4:結構體成員陣列大小為0
結構體陣列成員的大小為0是GNU C的一個特性。好處是可以在結構體中分配不定長的大小。如
typedef struct st
{
    inta;
    int b;
    char c[0];
}st_t;
sizeof(st_t)等於8,即char c[0]的大小為0.
34、位操作(Bit manipulation)

答: 嵌入式系統總是要使用者對變數或暫存器進行位操作。給定一個整型變數a,寫兩段程式碼,第一個設定a的bit 3,第二個清除a 的bit 3。在以上兩個操作中,要保持其它位不變。
對這個問題有三種基本的反應
1)不知道如何下手。該被面者從沒做過任何嵌入式系統的工作。
2) 用bit fields。Bit fields是被扔到C語言死角的東西,它保證你的程式碼在不同編譯器之間是不可移植的,同時也保證了的你的程式碼是不可重用的。我最近不幸看到 Infineon為其較複雜的通訊晶片寫的驅動程式,它用到了bit fields因此完全對我無用,因為我的編譯器用其它的方式來實現bit fields的。從道德講:永遠不要讓一個非嵌入式的傢伙粘實際硬體的邊。
3) 用 #defines 和 bit masks 操作。這是一個有極高可移植性的方法,是應該被用到的方法。最佳的解決方案如下:

#define BIT3 (0x1 << 3)
static int a;
void set_bit3(void) 
{
    a |= BIT3;
}
void clear_bit3(void) 
{
    a &= ~BIT3;
}
    一些人喜歡為設定和清除值而定義一個掩碼同時定義一些說明常數,這也是可以接受的。我希望看到幾個要點:說明常數、|=和&=~操作。