關于gcc擴展中的宏定義中用 # 和 ##

關于gcc擴展中的宏定義中用 "#" 和 "##"

今天測試了宏定義中的 "#" 和 "##" 的區別。

結果如下:

"#" 代表和一個字符串相連接

"##" 代表和一個符號連接,符號可以是變量,或另一個宏符號。

舉例如下:

宏定義如下

(1)

#define DEV_FILE_NAME??? "/dev/test_kft"

#define OPEN_FILE(fd, n)??? /
{?? /
??? fd = open(DEV_FILE_NAME #n,O_RDONLY); /
??? if(fd < 0) /
??? { /
?????? printf("Open device error/n"); /
??????? return 0; /
??? }?? /
}

如此調用:

??? 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:??? { fd1 = open("/dev/test_kft" "1",00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:??? { fd2 = open("/dev/test_kft" "2",00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:??? { fd3 = open("/dev/test_kft" "3",00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:??? { fd4 = open("/dev/test_kft" "4",00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:??? { fd5 = open("/dev/test_kft" "5",00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:??? { fd6 = open("/dev/test_kft" "6",00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

如果沒有定義DEV_FILE_NAME ,就是

2299:??? { fd1 = open(DEV_FILE_NAME "1",00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:??? { fd2 = open(DEV_FILE_NAME "2",00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:??? { fd3 = open(DEV_FILE_NAME "3",00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:??? { fd4 = open(DEV_FILE_NAME "4",00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:??? { fd5 = open(DEV_FILE_NAME "5",00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:??? { fd6 = open(DEV_FILE_NAME "6",00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

所以可以很清楚的看出#n 解析出來的是"n" , 用于連接一個已有的字符串。

(2) 再來看 ## 是什么意思, 宏定義如下:

#define OPEN_FILE(fd, n)??? /
{?? /
??? fd = open(DEV_FILE_NAME ##n,O_RDONLY); /
??? if(fd < 0) /
??? { /
?????? printf("Open device error/n"); /
??????? return 0; /
??? }?? /
}

調用方式相同。

看宏展開:

2299:??? { fd1 = open(DEV_FILE_NAME1,00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:??? { fd2 = open(DEV_FILE_NAME2,00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:??? { fd3 = open(DEV_FILE_NAME3,00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:??? { fd4 = open(DEV_FILE_NAME4,00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:??? { fd5 = open(DEV_FILE_NAME5,00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:??? { fd6 = open(DEV_FILE_NAME6,00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

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

#define DEV_FILE_NAME1??? "/dev/test_kft1"

再展開:


2299:??? { fd1 = open("/dev/test_kft1",00); if(fd1 < 0) { printf("Open device error/n"); return 0; } };
2300:??? { fd2 = open(DEV_FILE_NAME2,00); if(fd2 < 0) { printf("Open device error/n"); return 0; } };
2301:??? { fd3 = open(DEV_FILE_NAME3,00); if(fd3 < 0) { printf("Open device error/n"); return 0; } };
2302:??? { fd4 = open(DEV_FILE_NAME4,00); if(fd4 < 0) { printf("Open device error/n"); return 0; } };
2303:??? { fd5 = open(DEV_FILE_NAME5,00); if(fd5 < 0) { printf("Open device error/n"); return 0; } };
2304:??? { fd6 = open(DEV_FILE_NAME6,00); if(fd6 < 0) { printf("Open device error/n"); return 0; } };

很顯然第一個符號被替換了, 因為是符號是宏的緣故。 這樣我們也能把這一擴展特性應用在變量上。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454844.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454844.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454844.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 年計算_java實現計算某年某月的天數

在計算某年某月的天數時&#xff0c;需要注意平年閏年。分析&#xff1a;閏年具體的判定方法就要看它的判定條件&#xff1a;四年一閏 &#xff0c; 百年不閏 &#xff0c;400年再閏。而計算該年該月的天數&#xff0c;又分大月和小月&#xff0c;特殊月份2月之分。(視頻教程推…

添加自定義菜單,報錯40155

2019獨角獸企業重金招聘Python工程師標準>>> 提交的json中&#xff0c;某個自定義菜單對應的URL訪問是有問題的&#xff0c;請挨個檢查一下。 轉載于:https://my.oschina.net/selly1025/blog/1551496

gcc編譯流程及中間表示層RTL的探索

gcc編譯流程及中間表示層RTL的探索收藏新一篇: 解讀VC編程中的文件操作API和CFile類 | 舊一篇: Effective Item21 盡可能使用const 內容摘要 本文將以 C 語言為例&#xff0c;介紹 gcc 在接受一個 .c文件的輸入之后&#xff0c;其前端是如何進行處理并得到一個中間表示并轉交給…

【bzoj2132】圈地計劃 網絡流最小割

題目描述 最近房地產商GDOI(Group of Dumbbells Or Idiots)從NOI(Nuts Old Idiots)手中得到了一塊開發土地。據了解&#xff0c;這塊土地是一塊矩形的區域&#xff0c;可以縱橫劃分為NM塊小區域。GDOI要求將這些區域分為商業區和工業區來開發。根據不同的地形環境&#xff0c;每…

python爬蟲爬取數據如何將br去掉_Python怎么去除爬取下來的網站中的一些轉義字符串 - 收獲啦...

基本方法其實用python爬取網頁很簡單&#xff0c;只有簡單的幾句話這樣就可以獲得到頁面的內容。接下來再用正則匹配去匹配所需要的內容就行了。但是&#xff0c;真正要做起來&#xff0c;就會有各種各樣的細節問題。2.登錄這是一個需要登錄認證的網站。也不太難&#xff0c;只…

Linux基礎

Linux的特點&#xff1a; 系統版本&#xff1a;常見的有debian、Redhat更適合做服務器&#xff0c;更安全和穩定&#xff0c;Ubuntu唯一的優勢就是圖形界面好&#xff0c;centos目前被redhat收購&#xff0c;紅旗已經倒閉。 1、免費的/開源的&#xff1b;2、支持多線程/多用戶&…

GCC的編譯和調試--入門介紹

編譯與調試1.1編譯的概念和理解在進行C程序開發時&#xff0c;編譯就是將編寫的C語言代碼變成可執行程序的過程&#xff0c;這一過程是由編譯器來完成的。編譯器就是完成程序編譯工作的軟件&#xff0c;在進行程序編譯時完成了一系列復雜的過程。1.1.1程序編譯的過程在執行這一…

A* a=new B ,會不會產生內存泄露了,露了B-A的部分?

A* anew B ,delete a;會不會產生內存泄露了&#xff0c;露了B-A的部分。其中B為A的子類 析構函數在下邊3種情況時被調用&#xff1a;1.對象生命周期結束&#xff0c;被銷毀時&#xff1b;2.delete指向對象的指針時&#xff0c;或delete指向對象的基類類型指針&#xff0c;而其基…

spring 第一天:1015

對象加強的三種方法&#xff1a;1/繼承2/裝飾著模式3/動態調用 2&#xff1a;裝飾著模式&#xff1a;就是就是1-先建一個基類 &#xff0c;如咖啡類 。味道很苦2- 再建一個類配料類 也就是說是所欲配料種類的父類。然后寫多配料子類個子類繼承配料類&#xff0c;。3-子類三個步…

java public 繼承_java繼承問題

代碼&#xff1a;父類&#xff1a;public class Father {public Father() {System.out.println("基類構造函數{");show();new a();System.out.println("}");}public void show() {System.out.println("基類----show");}public class a {public a…

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圓環數(數位DP+惡心細節)

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圓環數 Time Limit: 5 Sec Memory Limit: 64 MBDescription 正如你所知&#xff0c;奶牛們沒有手指以至于不能玩“石頭剪刀布”來任意地決定例如誰先擠奶的順序。她們甚至也不能通過仍硬幣的方式。 所以她們通過"round number&q…

Optimizing Code with GCC

現在的編譯器越來越聰明&#xff0c;功能越來越強&#xff0c;從簡單的函數內聯&#xff0c;到復雜的寄存器分析&#xff0c;一系列代碼革命使程序運行得越來越快。大多數時候&#xff0c;更快比更小重要&#xff0c;因為磁盤空間和內存都變得便宜了。但是在嵌入式系統里&#…

QTP的那些事--操作excel的函數

1: QTP Excel函數 操作EXCEL 數據表格 表單 編輯EXCEL 工作表 2: Dim ExcelApp As Excel.Application 3: Dim excelSheet As Excel.worksheet 4: Dim excelBook As Excel.workbook 5: Dim fso As scrīpting.FileSystemObject 6: 7: ******************…

java-生產者消費者模式

經常會有公司叫我們手撕代碼&#xff0c;比如網易&#xff0c;阿里&#xff0c;那我們是不是該掌握下呢。下面這段代碼來自《現代操作系統》進程與線程P49頁。 public class ProducerConsumer {public ProducerConsumer() { }private static final int N 100;static Producer …

yum查詢已經安裝mysql_通過yum安裝mysql

在linux中安裝數據庫首選MySQL&#xff0c;Mysql數據庫的第一個版本就是發行在Linux系統上&#xff0c;其他選擇還可以有postgreSQL&#xff0c;oracle等在Linux上安裝mysql數據庫&#xff0c;我們可以去其官網上下載mysql數據庫的rpm包&#xff0c;http://dev.mysql.com/downl…

koa2-cookie-session

node.js的path.extname方法使用   由于該方法屬于path模塊&#xff0c;使用前需要引入path模塊&#xff08;var path require(“path”) &#xff09;   接收參數&#xff1a;   p path 路徑 path.extname(index.html)// returns.htmlpath.extname(index.)// returns.pat…

從程序員角度看ELF

從程序員角度看ELF原文:《 ELF:From The Programmers Perspective》作者&#xff1a;Hongjiu Lu <mailto: hjlnynexst.com>NYNEX Science & Technology, Inc. 500 Westchester Avenue White Plains, NY 10604, USA 翻譯&#xff1a;alert7 <mailto: alert721cn.co…

JAVA命令符找不到符號_[轉]Java命令行編譯文件時出現的錯誤,找不到符號或軟件包不存在等...

標簽(空格分隔)&#xff1a; Javajavascript習慣了eclipse的自動編譯&#xff0c;Java命令行編譯、執行文件只會最基礎的部分&#xff0c;就是對單文件的編譯和執行&#xff0c;并且不包含任何外部JAR包。但有時候你還非得用命令行&#xff0c;會碰到一些問題&#xff0c;博主這…

C#中POST數據和接收的幾種方式

POST方式提交數據&#xff0c;一種眾所周知的方式&#xff1a; html頁面中使用form表單提交&#xff0c;接收方式&#xff0c;使用Request.Form[""]或Request.QueryString[""]來獲取。 這里介紹另外一種POST方式和接收方式&#xff0c;就是將整個數據作為加…

java自動注入注解_Spring自動注解標簽@Autowired不能注入xml配置的bean嗎?

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓配置service的xmlservice代碼public class LoginServiceImpl extends BaseDaoServiceImpl implements LoginService {Overridepublic Map queryByUserName(String userName){IDao iDao super.getAppDao();return (Map)iDao.queryF…