C C 預處理操作符 和

2021-05-26 04:32:06 字數 3885 閱讀 6987

#的作用是將乙個帶參的函式巨集的引數轉換為乙個字串

並且只能用在這一場合

例:#define f(x) #x

printf("%s",f(love));

上面的輸出結果為love

##的作用是將乙個帶參的函式巨集的引數與乙個字串進行連線起來

例:#define f(x) dluf##x

int dluf5=6;

printf("%d",f(5));

上面的輸出結果為6

之一:剛才測試了巨集定義中的 "#" 和 "##" 的區別,希望能對大家有點幫助。:)

結果如下:

"#" 代表和乙個字串相連線

"##" 代表和乙個符號連線,符號可以是變數,或另乙個巨集符號。

舉例如下:

巨集定義如下

(1)

#define dev_file_name "/dev/test_kft"

#define open_file(fd, n) /

/ }

如此呼叫:

open_file(fd1, 1);

open_file(fd2, 2);

open_file(fd3, 3);

open_file(fd4, 4);

open_file(fd5, 5);

open_file(fd6, 6);

用gcc -e展開後,如下

2299: };

2300: };

2301: };

2302: };

2303: };

2304: };

如果沒有定義dev_file_name ,就是

2299: };

2300: };

2301: };

2302: };

2303: };

2304: };

所以可以很清楚的看出#n 解析出來的是"n" , 用於連線乙個已有的字串。

(2) 再來看 ## 是什麼意思, 巨集定義如下:

#define open_file(fd, n) /

/ }

呼叫方式相同。

看巨集展開:

2299: };

2300: };

2301: };

2302: };

2303: };

2304: };

現在看清楚了, ##n 的作用是把n直接連線在了乙個符號的末尾. 好, 現在我們定義乙個符號看看效果。

#define dev_file_name1 "/dev/test_kft1"

再展開:

2299: };

2300: };

2301: };

2302: };

2303: };

2304: };

很顯然第乙個符號被替換了, 因為是符號是巨集的緣故。 這樣我們也能把這一擴充套件特性應用在變數上。

from:

之二:

一,一般用法

我們使用#把巨集引數變為乙個字串,用##把兩個巨集引數貼合在一起.

用法:#include

#include

using namespace std;

#define str(s) #s

#define cons(a,b) int(a##e##b)

int main()

二,當巨集引數是另乙個巨集的時候

但雖要注意的是凡巨集定義裡有用'#'或'##'的地方巨集引數是不會再展開.

1, 非'#'和'##'的情況

#define tow (2)

#define mul(a,b) (a*b)

printf("%d*%d=%d/n", tow, tow, mul(tow,tow));

這行的巨集會被展開為 printf("%d*%d=%d/n", (2), (2), ((2)*(2)));

mul裡的引數tow會被展開為(2).

2, 當有'#'或'##'的時候

#define a 2

#define str(s) #s

#define cons(a,b) int(a##e##b)

printf("int max: %s/n", str(int_max)); // int_max #include

這行會被展開為printf("int max: %s/n", "int_max");

printf("%s/n", cons(a, a)); // compile error

這一行則是printf("%s/n", int(aea));

int_max和a都不會再被展開,

然而解決這個問題的方法很簡單. 加多一層中間轉換巨集.

#define a 2

#define _str(s) #s

#define str(s) _str(s) // 轉換巨集

#define _cons(a,b) int(a##e##b)

#define cons(a,b) _cons(a,b) // 轉換巨集

printf("int max: %s/n", str(int_max)); // int_max #include

printf("%s/n", cons(a, a));

加這層巨集的用意是把所有巨集的引數在這層裡全部展開, 那麼在轉換巨集裡的那乙個巨集(_str)就能得到正確的巨集引數.

三,'#'和'##'的一些應用特例

1, 合併匿名變數名

#define ___anonymous1(type, var, line) type var##line

#define __anonymous0(type,line) ___anonymous1(type, _anonymous, line)

#define anonymous(type) __anonymous0(type,__line__)

2,填充結構

#define fill(a)

typedef struct msgmsg;

enum;

msg _msg=;

3,記錄檔名

#define _get_file_name(f) #f

#define get_file_name(f) _get_file_name(f)

static char file_name=get_file_name(__file__);

4,得到乙個數值型別所對應的字串緩衝大小

#define _type_buf_size(type) sizeof #type

#define type_buf_size(type) _type_buf_size(type)

char buf[type_buf_size(int_max)];

itoa(2006, buf, 10);

from:

補充:

1, "##"用於定義結構體型別.

若結構體成員相同, 但是為了有所區別, 需要定義成不同的型別名, 此時用"##"就非常方便了. 比如, 定義乙個用於除錯的結構體型別:

struct operationresult_struct

;

但是我們想為http的除錯和檔案操作的除錯定義不同的型別名, 可以用如下方法.

用gcc -e 檢視預編譯結果.

關於C C 中的點操作符和箭頭操作符

ps 話說以前竟然一直沒有關注到這個問題啊。不應該啊。今天查了點資料,加上自己寫code的體會,說下一下,作為記錄吧。先概括一下 點操作符 用來引用普通物件。箭頭操作符 用來引用指標物件。舉例子說明一下 比如,我有乙個物件darkray。那麼我可以通過 來呼叫darkray類中中的成員變數。但是如果...

C C 中「 」操作符和「後 」操作符的優先順序

假設有如下的定義 char carr char cp carr 那麼表示式 cp 的右值是什麼呢?這個表示式在陣列遍歷的程式中非常常見,但我對於這個表示式的理解有些偏差,我一直認為它和下面的表示式是等價的。cp cp 即先對cp進行解引用操作,然後使cp指向陣列的下乙個位置。雖然說最終的結果是一樣的...

C C 之 操作符過載

1.成員函式過載操作符 除 外其他操作符都可過載 1 a.雙目操作符宣告格式 class 類名 b.雙目操作符定義格式 返回值型別 類名 operator 型別 c.雙目操作符使用格式 類名 a 類名 b a b 或a.operator b 2 a.單目操作符過載宣告格式 class 類名 b.單目...