是字串連線符的意思

2021-05-27 07:49:17 字數 2883 閱讀 5243

#define module_generic_table(gtype,name)                        \

extern const struct gtype##_id __mod_##gtype##_table            \

__attribute__ ((unused, alias(__stringify(name))))

用gcc預處理可以展開看巨集定義展開是怎麼樣的。

gcc -e x.c >x.log

核心中有很多的巨集定義,在巨集定義define中經常看到兩個字串##和#,這裡把它的用法做一下說明:

##是乙個連線符號,用於把引數連在一起

例如:> #define foo(arg) my##arg

則》 foo(abc)

相當於 myabc

#是「字串化」的意思。出現在巨集定義中的#是把跟在後面的引數轉換成乙個字串

例如:> #define strcpy(dst, src) strcpy(dst, #src)

則》 strcpy(buff, abc)

相當於 strcpy(buff, "abc")

另外,如果##後的引數本身也是乙個巨集的話,##會阻止這個巨集的展開。

#define strcpy(a, b) strcpy(a ## _p, #b)

int main()

/tell you about ## in common text

關於記號貼上操作符(token paste operator): ##

1. 簡單的說,「##」是一種分隔連線方式,它的作用是先分隔,然後進行強制連線。

其中,分隔的作用類似於空格。我們知道在普通的巨集定義中,預處理器一般把空格

解釋成分段標誌,對於每一段和前面比較,相同的就被替換。但是這樣做的結果是,

被替換段之間存在一些空格。如果我們不希望出現這些空格,就可以通過新增一些

##來替代空格。

另外一些分隔標誌是,包括操作符,比如 +, -, *, /, [,], ...,所以儘管下面的

巨集定義沒有空格,但是依然表達有意義的定義: define add(a, b) a+b

而其強制連線的作用是,去掉和前面的字串之間的空格,而把兩者連線起來。

2. 舉列 -- 試比較下述幾個巨集定義的區別

#define a1(name, type) type name_##type##_type 或

#define a2(name, type) type name##_##type##_type

a1(a1, int);  

a2(a1, int);  

解釋:1) 在第乙個巨集定義中,"name"和第乙個"_"之間,以及第2個"_"和第二個

"type"之間沒有被分隔,所以預處理器會把name_##type##_type解釋成3段:

「name_」、「type」、以及「_type」,這中間只有「type」是在巨集前面出現過

的,所以它可以被巨集替換。

2) 而在第二個巨集定義中,「name」和第乙個「_」之間也被分隔了,所以

預處理器會把name##_##type##_type解釋成4段:「name」、「_」、「type」

以及「_type」,這其間,就有兩個可以被巨集替換了。

3) a1和a2的定義也可以如下:

#define a1(name, type) type name_ ##type ##_type  

<##前面隨意加上一些空格》

#define a2(name, type) type name ##_ ##type ##_type

結果是## 會把前面的空格去掉完成強連線,得到和上面結果相同的巨集定義

3. 其他相關 -- 單獨的乙個 #

至於單獨乙個#,則表示 對這個變數替換後,再加雙引號引起來。比如

#define __stringify_1(x) #x

那麼__stringify_1(linux) <==> "linux"

所以,對於module_device_table

1) #define module_device_table(type,name)  

module_generic_table(type##_device,name)

2) #define module_generic_table(gtype,name)  

extern const struct gtype##_id __mod_##gtype##_table  

__attribute__ ((unused, alias(__stringify(name))))

得到  

module_device_table(usb, products)  

<==> module_generic_table(usb_device,products)

<==> extern const struct usb_device_id __mod_usb_device_table  

__attribute__ ((unused, alias("products")))  

注意到alias attribute需要乙個雙引號,所以在這裡使用了__stringify(name)來

給name加上雙引號。另外,還注意到乙個外部變數"__mod_usb_device_table"被alias

到了本驅動專用的由使用者自定義的變數products是如何使用的,更多的資訊請參看《probe()過程分析》。

4. 分析方法和驗證方式 -- 編寫乙個簡單的c程式

用巨集定義乙個變數,同時用直接方式定義乙個相同的變數,編譯報告重複定義;

用巨集定義乙個變數,直接使用該巨集定義的變數名稱,編譯通過且執行結果正確;

使用printf列印字串資料。printf("token macro is %s", __stringify_1(a1));

scss 字串連線符

運算可用於連線字串 scss p 編譯後的 css 樣式 p 請注意,如果帶引號的字串被新增到不帶引號的字串中 也就是說,帶引號的字串在 的左側 那麼返回的結果是帶引號的字串。同樣,如果乙個不帶引號的字串新增到帶引號的字串中 不帶引號的字串在 的左側 那麼返回的結果是乙個不帶引號的字串。例如 scs...

資料庫物件 字串連線符

比如我想要乙個這樣的字串 select from test where sj 2009 04 1 and sj 2009 5 1 然我們申請的變數是這樣的 declare str1 varchar2 100 2009 04 1 str2 varchar2 100 2009 5 1 sqlstr va...

字串連線

輸入n個字串s i 你要把他們按某個順序連線起來,使得字典序最小。1 n 100 每個字串長度 100 字串只包含小寫字母 input 第一行乙個整數n。接下來每行乙個字串s i output 一行乙個字串表示把輸入的n個字串按某個順序連線之後的結果input示例 6 itlooks like an...