網站首頁 編程語言 正文
??1.#define定義標識符
在C語言程序中,有時候會包含#define
#define可以定義標識符
也就是說可以對字符重新定義,實現代替的作用
??語法
#define? name? stuff?
就比如說:
#define MAX 1000(用MAX代替1000)
#define reg? ?register (用reg代替register)
??舉個栗子
#include#define MAX 100 int main() { printf("%d", MAX); return 0; }
當代碼運行的時候
在代碼編譯的預處理階段 就會把宏替換為文本程序代碼
代替的結果如下:
#includeint main() { printf("%d", 100); return 0; }
??注意:#define定義標識符后面盡量不加上分號,因為如果加上的話,在替換的過程中,分號也會別替換到文本程序中,有時候會導致出現邏輯錯誤。
??2.#define定義宏
#define規定允許將參數替換到文本中,這樣包含參數叫做#define定義宏
宏在程序中,執行的速度更快,因為相對于函數,宏沒有函數的調用和返回的開銷
語法:
#define SQUARE(x)? ?x*x
這與#define定義宏一樣,都是完成替換的,不過#define定義宏后面有一個括號,包含參數
??下面用#define定義宏來實現兩個數求最大值
#include#define MAX(x,y) ((x)>(y)?(x):(y)) int main() { int a = 20; int b = 10; int c = MAX(a,b); printf("%d", c); return 0; }
替換后的結果為:
#includeint main() { int a = 20; int b = 10; int c = a>b?a:b; printf("%d", c); return 0; }
?在#define定義宏的時候,后面的參數盡量帶上括號,使每一個參數相對獨立
這樣可以避免由于操作符的優先級不同,導致最終的邏輯就錯了
舉個栗子:
#include#define sum(x) x*x int main() { int ret = sum(3 + 3); printf("%d", ret); }
如果不仔細觀察的話,可能你認為的結果就是36
這個代碼的計算過程為:3+3*3+3,并不是(3+3)*(3+3)
??#define替換的規則
#define定義標識符和宏時,程序會繼續如下步驟
1.在定義宏時,先對參數進行檢查,如果參數里包含有#define定義的標識符時,首先完成相應的替換
?
2.替換文本會隨后插入到原來文本文件中,對于宏來說,參數名被他們的值所替換
?
3.最后進行檢查,果然還有#define定義的符號,將重復上述的操作
?注意:
1.#define參數中可以包含其他由#define定義的標識符,但是#define不能遞歸
2.如果#define的參數名存在在字符串中,將不會完成替換
??#與## #的用法:
在不確定參數的情況下,可以使用 “#n” ,可以實現不同字符串的插入
效果如下:
#include#define PRINT(n) printf("the value of "#n" is %d\n",n); int main() { int a = 10; PRINT(a); int b = 20; PRINT(b); int c= 30; PRINT(c); return 0; }
??替換后的效果為:
#includeint main() { int a = 10; printf("the value of" "a" " is %d\n",a); PRINT(a); int b = 20; PRINT(b); printf("the value of " "b" " is %d\n",b); int c= 30; PRINT(c); printf("the value of " "c" " is %d\n",c); return 0; }
##的用法:
#include#define CAT(Max,num) Max##nu int main() { int Maxnum = 100; printf("%d", Maxnum); return 0; }
雙##的用法可以拼接兩個字符串
當然這個前提是拼接后的字符串必須產生一個合法的標識符,否則結果就是未定義的
??宏的缺點
?1.如果使用宏過多,宏定義的代碼插入到程序中,會大幅度增加程序的長度
2.宏是沒法調試的
3.宏與類型無關,導致程序不夠嚴謹
4.宏會帶來優先級的問題,容易導致程序的錯誤
???宏和函數的優缺點 ? ? ?
1).在代碼長度角度上,因為宏是直接替換所以若宏較長會增加代碼長度
2).在執行速度上,宏較函數快,因為函數存在調用/返回時的額外開銷
3).在參數求值方面,define定義的宏可能會具有副作用會導致修改變量最后的值,而函數即使調用多次也不會修改變量原來的值
4).在參數類型方面,宏與類型無關,所以宏是可以傳參數的而函數不行在C中函數是不可以傳類型的
?5).在是否可調試方面,宏不可調試,函數可調試宏可以傳類型的檢測,實現malloc(動態開辟內存的函數)
#include#include #define MALLOC(COUNT,TYPE)\ (TYPE *)alloc(COUNT*sizeof(TYPE)) void *alloc(int sz) //宏可以傳類型,函數不可以傳類型 { void *p=malloc(sz); if(p == NULL) { printf("out of memory\n"); exit(EXIT_FAILURE); } return p; } int main() { int i=0; int *p=MALLOC(10,int); for(i=0;i<10;i++) { *(p+i)=i; } for(i=0;i<10;i++) { printf("%d ",*(p+i)); } free(p); system("pause"); return 0; }
總結
原文鏈接:https://blog.csdn.net/m0_64332179/article/details/123227653
相關推薦
- 2022-05-22 分享jQuery的3種常見事件監聽方式_jquery
- 2022-08-02 python監控日志中的報錯并進行郵件報警_python
- 2022-11-14 Python語言中Tuple的由來分析_python
- 2022-04-09 用C語言實現簡單的計算器功能_C 語言
- 2022-07-25 Redisson如何解決Redis分布式鎖提前釋放問題_Redis
- 2022-06-02 Docker部署項目完全使用指南(小結)_docker
- 2022-04-15 python實現請求數據包簽名_python
- 2022-10-04 C++超詳細梳理lambda和function的使用方法_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支