日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【⚠️阴沟里翻船,这题都做错了!⚠️】C语言宏定义

發布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【⚠️阴沟里翻船,这题都做错了!⚠️】C语言宏定义 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

快答題!直接上題,10秒之內報出a的值是多少!

#include<stdio.h> #define SQR(x) x*x int main() {int a = 10, k = 2, m = 1;a/=SQR(k + m)/SQR(k + m);printf("%d\n", a); }

大家答完了可以到文章末尾進行投票

楔子

今天刷blink,看到一個新人在請教問題,題目代碼如上,問a的值是多少。我看代碼沒幾行,就想當然的腦算了一下,覺得結果肯定是10啊,但是本著負責的態度,還是把代碼又敲了一遍,一看打印是1,我擦,翻車了。
于是乎,加打印排查。最后發現是宏的展開問題。這個函數宏少加了一個括號,展開時很容易出錯。看來對宏還是理解不透徹啊!哪里跌到哪里爬起來!抓緊學起來~

宏定義

概念

C語言中的宏定義實現的是一個文本替換的功能。#define命令是C語言中的一個宏定義命令,它用來將一個標識符定義為一個字符串,該標識符被稱為宏名,被定義的字符串稱為替換文本。
命令有兩種格式:

  • 簡單宏定義:#define 標識符 記號序列
    示例:#define INT_MAX 2147483647
    將使得預處理器把該標識符后續出現的各個實例用給定的記號序列替換。記號序列前后的空白符將被丟棄。第二次使用#define指令定義同一標識符是錯誤的,除非第二次定義中的標記序列與第一次相同(所有空白分隔符被認為是相同的)。

  • 帶參數的宏定義#define 標識符(標識符表opt) 記號序列
    示例:#define MAX(a,b) ((a>b)?(a):(b))
    帶有形式參數(由標識符表指定)的宏定義的第一個標識符與圓括號(之間沒有空格。記號序列前后的空白符也會被丟棄。如果要對宏進行重定義,則必須保證其形式參數個數、拼寫及記號序列都必須與前面的定義相同。

取消宏定義

#undef 標識符用于取消標識符的預處理器定義。將#undef應用于未知標識符(即未使用#define指令定義的標識符)并不會導致錯誤。
示例:#undef INT_MAX

注意點

針對帶參數的宏定義,宏標識符(后面可以跟一個空白符,空白符是可選的)及其后用一對圓括號括起來的、由逗號分隔的記號序列就構成了一個宏調用。宏調用的實際參數是用逗號分隔的記號序列,用引號或嵌套的括號括起來的逗號不能用于分隔實際參數。在處理過程中,實際參數不進行宏展開。宏調用時,實際參數的數目必須與定義中形式參數的數目匹配。實際參數被分離后,前導和尾部的空白符將被刪除。隨后,由各個實際參數產生的記號序列中的形式參數的前面一個#符號,或者其前面或后面有一個##符號,否則,在插入前要對宏調用的實際參數記號進行檢查,并在必要時進行擴展。

兩個特殊的運算符會影響替換過程。首先,如果替換記號序列中的某個形式參數前面直接是一個#符號(它們之間沒有空白符),相應形式參數的兩邊將被加上雙引號",隨后,#和形式參數標識符將被用引號引起來的實際參數替換。實際參數中的字符串字面值、字符常量兩邊或內部的每個雙引號""或反斜杠\前面都要插入一個反斜杠\。

其次,無論哪種宏的定義記號序列中包含一個##運算符,在形式參數替換后都要把##及其前后的空白符都刪除掉,以便將相鄰記號連接起來形成一個新記號。如果這樣產生的記號無效,或者結果依賴于##運算符的處理順序,則結果沒有定義。同時,##也可以不出現在替換記號序列的開頭或者結尾。

對這兩種類型的宏,都要重復掃描替換記號序列以查找更多的已定義標識符。但是,當某個標識符在某個標識符在某個擴展中被替換后,再次掃描并再次遇到此標識符時不再對其執行替換,而是保持不變。

即使執行宏擴展后得到的最終結果以#打頭,也不認為它是預處理指令。

函數宏與函數不同點

#define ABSDIFF(a, b) ((a)>(b) ? (a)-(b) : (b)-(a))
這宏定義它返回兩個參數差的絕對值。與執行同樣功能的函數不同的是,參數與返回值可以是任意算術類型,甚至可以是指針。同時,參數可能有副作用,而且需要計算兩次,一次進行測試,另一次則生成值。

宏的展開過程流程圖:

Demo

#include<stdio.h>#define tmpfile(dir) #dir "%s"#define cat(x, y) x ## y #define xcat(x, y) cat(x,y)int main() {printf("%s\r\n", tmpfile(/usr/tmp));printf("%d\r\n", xcat(xcat(1, 2), 3)); }///< 打印信息: ///< usr/tmp%s ///< 123

引經據典

https://gaomf.cn/2017/10/06/C_Macro/
https://zhuanlan.zhihu.com/p/70366235
《The C Programming Language Second Edtion》

總結

以上是生活随笔為你收集整理的【⚠️阴沟里翻船,这题都做错了!⚠️】C语言宏定义的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。