C語(yǔ)言宏定義#define的使用
宏定義是高級(jí)語(yǔ)言編譯器提供的常用語(yǔ)法,其目的是利用某一標(biāo)識(shí)符標(biāo)識(shí)某個(gè)文本字符串。在編寫程序時(shí),如果程序中反復(fù)地使用某個(gè)數(shù)據(jù)或某段程序片段,就可以考慮將這個(gè)數(shù)據(jù)或程序片段定義為宏,然后每個(gè)出現(xiàn)該數(shù)據(jù)或程序片段的地方用宏名替代,選擇宏定義來(lái)做的好處是程序簡(jiǎn)潔,可讀性好,而且當(dāng)需要修改這些相同的程序片段時(shí),只要修改宏定義中的字符串即可,不需要修改多處。
宏定義命令:define
優(yōu)點(diǎn):方便程序的修改,同時(shí)也能提高程序的運(yùn)行效率。
宏定義一般有兩種形式:無(wú)參宏定義和帶參宏定義。
無(wú)參宏定義
定義形式
#define 標(biāo)識(shí)符 字符串
注意:
1.宏定義是用宏名來(lái)表示一個(gè)字符串,在宏展開時(shí)以該字符串取代宏名,只是簡(jiǎn)單的替換,字符串中可以含任何字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理不作任何檢查。只在編譯時(shí)檢查。
2.宏定義行末不必加分號(hào)(除非你的宏內(nèi)容中需要有分號(hào))。
3.宏定義必須寫在函數(shù)之外,作用域?yàn)楹甓x命令起到源程序結(jié)束。如要終止其作用域可使用#undef命令
例1:輸入圓的半徑輸出圓的周長(zhǎng)和面積
#include <stdio.h> #define PI 3.14 int main(){ int r; printf("輸入半徑:"); scanf("%d",&r); printf("圓的周長(zhǎng)為:%.2f,面積為:%.2f",2*PI*r,PI*r*r); return 0; }
預(yù)處理階段進(jìn)行宏替換↓:
#include <stdio.h> int main(){ int r; printf("輸入半徑:"); scanf("%d",&r); printf("圓的周長(zhǎng)為:%.2f,面積為:%.2f",2*3.14*r,3.14*r*r); return 0; }
代碼輸出:
例2:通過(guò)宏定義輸出字符串
#include <stdio.h> #define HELLO "Hello," #define WORLD "World!" int main(){ printf(HELLO WORLD); return 0; }
預(yù)處理階段進(jìn)行宏替換↓:
#include <stdio.h> int main(){ printf("Hello," "World!"); return 0; }
代碼輸出:
例3:請(qǐng)問(wèn)如下代碼S1和S2的輸出是否相等
#include <stdio.h> #define S1 3+4 #define S2 (3+4) int main(){ printf("S1:%d\n",S1*5); printf("S2:%d\n",S2*5); return 0; }
預(yù)處理進(jìn)行宏替換↓(這里就體現(xiàn)出了直接替換并不會(huì)因?yàn)槟愕暮晗榷x就先計(jì)算,而是替換后再做后續(xù)處理):
#include <stdio.h> #define S1 3+4 #define S2 (3+4) int main(){ printf("S1:%d\n",3+4*5); printf("S2:%d\n",(3+4)*5); return 0; }
代碼輸出:
帶參宏定義
定義形式
#define 宏名(形參表) 字符串
例1:M(3)==N(3)? M(3+2)==N(3+2)?
#include<stdio.h> #define M(y) ((y)*(y)+3*(y)) #define N(y) (y*y+3*y) int main(){ printf("M(3):%d\n",M(3)); printf("N(3):%d\n",N(3)); printf("M(3+2):%d\n",M(3+2)); printf("N(3+2):%d\n",N(3+2)); }
預(yù)處理階段進(jìn)行宏替換↓(這個(gè)例題主要是為了提醒大家如果要用宏定義進(jìn)行一些計(jì)算,最好將參與計(jì)算的所有變量都加上括號(hào)以防本題中的情況出現(xiàn)):
#include<stdio.h> #define M(y) ((y)*(y)+3*(y)) #define N(y) (y*y+3*y) int main(){ printf("M(3):%d\n",((3)*(3)+3*(3))); printf("N(3):%d\n",(3*3+3*3)); printf("M(3+2):%d\n",((3+2)*(3+2)+3*(3+2))); printf("N(3+2):%d\n",(3+2*3+2+3*3+2)); }
代碼輸出:
例2:通過(guò)宏來(lái)計(jì)算數(shù)組中元素個(gè)數(shù)
#include<stdio.h> #include<stdlib.h> #include<time.h> #define Size_Array(b) sizeof(b)/sizeof(b[0]) int main(){ int i; srand((unsigned)time(NULL)); int b[i=rand()%100]; printf("隨機(jī)數(shù)為:%d 數(shù)組元素個(gè)數(shù)為:%d",i,Size_Array(b)); }
預(yù)處理階段進(jìn)行宏替換↓(很經(jīng)典的面試小題):
#include<stdio.h> #include<stdlib.h> #include<time.h> int main(){ int i; srand((unsigned)time(NULL)); int b[i=rand()%100]; printf("隨機(jī)數(shù)為:%d 數(shù)組元素個(gè)數(shù)為:%d",i,sizeof(b)/sizeof(b[0])); }
代碼輸出:
#和##運(yùn)算
#運(yùn)算 用法:
# 運(yùn)算符的用處就是把符號(hào)轉(zhuǎn)化為字符串。例如,如果 a 是一個(gè)宏的形參,則替換文本中的 #a 則被系統(tǒng)轉(zhuǎn)化為 “a”。
#include <stdio.h> #define TO_STR(s) #s int main(){ printf(TO_STR(HelloWorld!)); return 0; }
代碼輸出:
##運(yùn)算 用法:
## 運(yùn)算符可以用在替換文本中,而它的作用是起到粘合的作用,即將兩個(gè)符號(hào)組合成一個(gè)符號(hào)。
#include <stdio.h> #define CONCAT(x,y) x##y int main(){ printf("%d", CONCAT(1,000)); return 0; }
代碼輸出:
變參宏
用法:
當(dāng)要調(diào)用printf類似不確定參數(shù)格式時(shí)可以使用__VA_ARGS__,在宏定義中,形參列表的最后一個(gè)參數(shù)為省略號(hào)“…”,“__VA_ARGS__”就可以被用在替換文本中,來(lái)表示“…”代表了什么。
#define PR(...) printf(__VA_ARGS__) //宏定義 PR("hello\n"); //宏調(diào)用
例:
#include <stdio.h> #define P(X, ...) printf("get:"#X":"__VA_ARGS__) int main(){ int j=20,i=10; P(10, "j = %d\n", j); P(10, "j = %d i=%d\n", j,i); return 0; }
代碼輸出:
#ifndef 條件編譯
#ifndef 的最主要目的是防止頭文件的重復(fù)包含和編譯?! ?/p>
c語(yǔ)言中,對(duì)同一個(gè)變量或者函數(shù)進(jìn)行多次聲明不會(huì)報(bào)錯(cuò)。所以如果.h文件里進(jìn)行了聲明工作,不使用# ifndef宏定義,多個(gè)c文件包含同一個(gè).h文件也不會(huì)報(bào)錯(cuò)。
然而c++中,#ifdef的作用域只是在單個(gè)文件中。所以如果.h文件里定義了全局變量,即使采用#ifdef宏定義,多個(gè).c文件包含同一個(gè).h文件就會(huì)出現(xiàn)全局變量重定義的錯(cuò)誤。
使用#ifndef可以避免這種錯(cuò)誤:
#ifndef x //先測(cè)試x是否被宏定義過(guò) #define x code1 //如果x沒(méi)有被宏定義過(guò),定義x,并編譯code1 #endif code2 //如果x已經(jīng)定義過(guò)了則編譯code2,跳過(guò)code1
適當(dāng)?shù)氖褂脳l件編譯和宏定義可以讓代碼的運(yùn)行效率更高,特別是在進(jìn)行大項(xiàng)目的時(shí)候當(dāng)某個(gè)數(shù)值使用次數(shù)較多且修改比較頻繁的情況下,宏定義也是比較高效的(當(dāng)然函數(shù)也可以,等有時(shí)間寫完函數(shù)再來(lái)比較一下函數(shù)和宏的優(yōu)缺點(diǎn)吧)
到此這篇關(guān)于C語(yǔ)言宏定義#define的使用的文章就介紹到這了,更多相關(guān)C語(yǔ)言宏定義#define內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)(多文件)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12詳解C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn)
這篇文章主要介紹了C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn),建造者模式將一個(gè)復(fù)雜對(duì)象的構(gòu)建于它的表現(xiàn)分離,可以減少代碼冗余,需要的朋友可以參考下2016-03-03C語(yǔ)言軟件spi虛擬總線中間層設(shè)計(jì)詳解
這篇文章主要為大家介紹了C語(yǔ)言軟件spi虛擬總線中間層設(shè)計(jì)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01C++小練習(xí)之高性能實(shí)現(xiàn)字符串分割
字符串分割是日常工作中比較常見的基礎(chǔ)函數(shù),通常大家會(huì)使用現(xiàn)成的基礎(chǔ)庫(kù),基礎(chǔ)庫(kù)的性能是否是最佳的,本文主要和大家探討一下如何最大限度的提升字符串分割的性能,希望對(duì)大家有所幫助2023-10-10java 出現(xiàn)NullPointerException的原因及解決辦法
這篇文章主要介紹了java 出現(xiàn)NullPointerException的原因及解決辦法的相關(guān)資料,這里說(shuō)明出現(xiàn)NullPointerException 的原因的總結(jié),并說(shuō)明該如何解決,需要的朋友可以參考下2017-08-08