很多優(yōu)秀的代碼,都會借用預(yù)編譯指令來完善代碼,今天就來講講關(guān)于預(yù)編譯指令的內(nèi)容。
常見的預(yù)處理指令如下:
#指令,無任何效果
#include含一個源代碼文件
#define義宏
#undef消已定義的宏
#if果給定條件為真,則編譯下面代碼
#ifdef果宏已經(jīng)定義,則編譯下面代碼
#ifndef果宏沒有定義,則編譯下面代碼
#elif果前面的if定條件不為真,當(dāng)前條件為真,則編譯下面代碼
#endif束一個if……#else件編譯塊
#error止編譯并顯示錯誤信息
本來只是想了解一下#ifdef,#ifndef,#endif的,沒想到查出來這么多的預(yù)處理指令,上面的多數(shù)都是常見的,但是平時沒有怎么注意預(yù)處理這方面的內(nèi)容,所以這里梳理一下知識吧。
同時有什么不妥的地方,或者遺漏了什么內(nèi)容,還請留言指出。
什么是預(yù)處理指令?
預(yù)處理指令是以#號開頭的代碼行。#號必須是該行除了任何空白字符外的第一個字符。#后是指令關(guān)鍵字,在關(guān)鍵字和#號之間允許存在任意個數(shù)的空白字符。整行語句構(gòu)成了一條預(yù)處理指令,該指令將在編譯器進(jìn)行編譯之前對源代碼做某些轉(zhuǎn)換。
預(yù)處理指令是在編譯器進(jìn)行編譯之前進(jìn)行的操作,對其進(jìn)行初步的轉(zhuǎn)換,產(chǎn)生新的源代碼提供給編譯器??梢婎A(yù)處理過程先于編譯器對源代碼進(jìn)行處理。在很多編程語言中,并沒有任何內(nèi)在的機(jī)制來完成如下一些功能:在編譯時包含其他源文件、定義宏、根據(jù)條件決定編譯時是否包含某些代碼(防止重復(fù)包含某些文件)。
要完成這些工作,就需要使用預(yù)處理程序。盡管在目前絕大多數(shù)編譯器都包含了預(yù)處理程序,但通常認(rèn)為它們是獨(dú)立于編譯器的。預(yù)處理過程讀入源代碼,檢查包含預(yù)處理指令的語句和宏定義,并對源代碼進(jìn)行響應(yīng)的轉(zhuǎn)換。預(yù)處理過程還會刪除程序中的注釋和多余的空白字符。#include包含一個源代碼文件這個預(yù)處理指令,我想是見得最多的一個,簡單說一下;
第一種方法是用尖括號把頭文件括起來。
#include 《stdio.h》
這種格式告訴預(yù)處理程序在編譯器自帶的或外部庫的頭文件中搜索被包含的頭文件。
第二種方法是用雙引號把頭文件括起來。
#include “test.h”
這種格式告訴預(yù)處理程序在當(dāng)前被編譯的應(yīng)用程序的源代碼文件中搜索被包含的頭文件,如果找不到,再搜索編譯器自帶的頭文件。采用兩種不同包含格式的理由在于,編譯器是安裝在公共子目錄下的,而被編譯的應(yīng)用程序是在它們自己的私有子目錄下的。
一個應(yīng)用程序既包含編譯器提供的公共頭文件,也包含自定義的私有頭文件。采用兩種不同的包含格式使得編譯器能夠在很多頭文件中區(qū)別出一組公共的頭文件。#define定義宏有關(guān)#define這個宏定義,在C語言中使用的很多,因為#define存在一些不足,C++強(qiáng)調(diào)使用const來定義常量。宏定義了一個代表特定內(nèi)容的標(biāo)識符。預(yù)處理過程會把源代碼中出現(xiàn)的宏標(biāo)識符替換成宏定義時的值。記住僅僅是進(jìn)行標(biāo)識符的替換。下面列舉一些#define的使用:
用#define實現(xiàn)求最大值和最小值的宏
#include 《stdio.h》
#define MAX(x,y) (((x)》(y))?(x):(y))
#define MIN(x,y) (((x)《(y))?(x):(y))
int main(void)
{
#ifdef MAX //判斷這個宏是否被定義
printf(“3 and 5 the max is:%d
”,MAX(3,5));
#endif
#ifdef MIN
printf(“3 and 5 the min is:%d
”,MIN(3,5));
#endif
return 0;
}
/*
* (1)三元運(yùn)算符要比if,else效率高
* (2)宏的使用一定要細(xì)心,需要把參數(shù)小心的用括號括起來,
* 因為宏只是簡單的文本替換,不注意,容易引起歧義錯誤。
*/
宏定義的錯誤使用
#include 《stdio.h》#define SQR(x) (x*x)int main(void)
{
int b=3;
#ifdef SQR//只需要宏名就可以了,不需要參數(shù),有參數(shù)的話會警告
printf(“a = %d
”,SQR(b+2));
#endif
return 0;
}
/*
*首先說明,這個宏的定義是錯誤的。并沒有實現(xiàn)程序中的B+2的平方
* 預(yù)處理的時候,替換成如下的結(jié)果:b+2*b+2
* 正確的宏定義應(yīng)該是:#define SQR(x) ((x)*(x))
* 所以,盡量使用小括號,將參數(shù)括起來。
*/
宏參數(shù)的連接
#include 《stdio.h》#define STR(s) #s#define CONS(a,b) (int)(a##e##b)int main(void)
{
#ifdef STR
printf(STR(VCK));
#endif#ifdef CONS
printf(“
%d
”,CONS(2,3));
#endif
return 0;
}
/* (絕大多數(shù)是使用不到這些的,使用到的話,查看手冊就可以了)
* 第一個宏,用#把參數(shù)轉(zhuǎn)化為一個字符串
* 第二個宏,用##把2個宏參數(shù)粘合在一起,及aeb,2e3也就是2000
*/
用宏得到一個字的高位或低位的字節(jié)
#include 《stdio.h》#define WORD_LO(xxx) ((byte)((word)(xxx) & 255))#define WORD_HI(xxx) ((byte)((word)(xxx) 》》 8))int main(void)
{
return 0;
}
/*
* 一個字2個字節(jié),獲得低字節(jié)(低8位),與255(0000,0000,1111,1111)按位相與
* 獲得高字節(jié)(高8位),右移8位即可。
*/
用宏定義得到一個數(shù)組所含元素的個數(shù)
#include 《stdio.h》#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))int main(void)
{
int array[100];
#ifdef ARR_SIZE
printf(“array has %d items.
”,ARR_SIZE(array));
#endif
return 0;
}
/*
*總的大小除以每個類型的大小
*/
關(guān)于#define宏的使用,應(yīng)該特別小心,尤其是含有參數(shù)計算的時候如下2示例,最保險的做法將參數(shù)用括號括起來。#ifdef,#ifndef,#endif.。。的使用以上這些預(yù)編譯指令,都是條件編譯指令,也就是說,將決定那些代碼被編譯,而哪些不被編譯。
示例1:
#include 《stdio.h》#include 《stdlib.h》#define DEBUGint main(void)
{
int i = 0;
char c;
while(1)
{
i++;
c = getchar();
if(‘
’ != c)
{
getchar();
}
if(‘q’ == c || ‘Q’ == c)
{
#ifdef DEBUG//判斷DEBUG是否被定義了
printf(“We get:%c,about to exit.
”,c);
#endif
break;
}
else
{
printf(“i = %d”,i);
#ifdef DEBUG
printf(“,we get:%c”,c);
#endif
printf(“
”);
}
}
printf(“Hello World!
”);
return 0;
}
/*#endif用于終止#if預(yù)處理指令。*/
ifdef 和 #ifndef
#include 《stdio.h》#define DEBUG
main()
{
#ifdef DEBUG
printf(“yes ”);
#endif#ifndef DEBUG
printf(“no ”);
#endif
}
//#ifdefined等價于#ifdef;//#if!defined等價于#ifndef
#else指令
#elif指令
其他一些指令
#error指令將使編譯器顯示一條錯誤信息,然后停止編譯。
#line指令可以改變編譯器用來指出警告和錯誤信息的文件號和行號。
#pragma令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告信息。
編輯:jq
-
C++
+關(guān)注
關(guān)注
22文章
2114瀏覽量
73899 -
代碼
+關(guān)注
關(guān)注
30文章
4841瀏覽量
69143 -
編譯器
+關(guān)注
關(guān)注
1文章
1642瀏覽量
49318 -
編譯
+關(guān)注
關(guān)注
0文章
663瀏覽量
33074
原文標(biāo)題:預(yù)編譯指令常見用法
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
Triton編譯器如何提升編程效率
Triton編譯器的優(yōu)化技巧
Triton編譯器的常見問題解決方案
數(shù)控車床m99指令的用法
淺談Vivado編譯時間
![<b class='flag-5'>淺談</b>Vivado<b class='flag-5'>編譯</b>時間](https://file1.elecfans.com/web2/M00/06/B7/wKgZombqPm-AQ__dAADm1cI9n3M572.jpg)
三菱PLC傳送指令的用法
PLC中SFTL指令的用法
數(shù)控車床m99指令的用法
STVD中如何設(shè)置預(yù)編譯選項?
常見的PLC通信指令有哪些呢?
Vivado編譯常見錯誤與關(guān)鍵警告梳理與解析
HighTec Tricore編譯速度優(yōu)化策略探討
![HighTec Tricore<b class='flag-5'>編譯</b>速度優(yōu)化策略探討](https://file1.elecfans.com/web2/M00/C8/A0/wKgaomYWGV2AYPo0AAAPok0cS84452.png)
評論