C語言必備知識(shí)編譯預(yù)處理
編譯預(yù)處理就是在編譯源代碼之前進(jìn)行的一系列處理,將源程序中的一些特殊命令進(jìn)行展開或處理,生成擴(kuò)展的源代碼。這些特殊命令通常以“#”開頭,占單獨(dú)的行,語句尾部不需要加分號(hào)。
宏定義
(#define)是一種常見的編譯預(yù)處理指令,用于定義宏,實(shí)現(xiàn)代碼的簡化和重用。
文件包含(#include)用于在源文件中引入其他文件的內(nèi)容,方便代碼模塊化和復(fù)用。
條件編譯
(#if, #else, #endif等)允許根據(jù)條件選擇性地編譯部分代碼,提高代碼的靈活性。
在預(yù)處理階段,這些指令會(huì)被解釋和處理,生成經(jīng)過預(yù)處理的源代碼,然后再經(jīng)過編譯、匯編、鏈接等步驟生成最終的可執(zhí)行文件。這個(gè)過程有助于提高代碼的可維護(hù)性和可移植性。
書寫格式
以“#”開頭、占單獨(dú)行、語句尾不加分號(hào)。這樣的規(guī)范有助于編譯器正確解釋和處理這些指令,同時(shí)也使得代碼更加清晰易讀。這樣的一致性規(guī)范有助于維護(hù)代碼時(shí)的可讀性和可理解性。
宏定義的例子
// 定義常量
#include < stdio.h >
#define MAX_SIZE 100
#define PI 3.1415926
// 簡化代碼
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define DEBUG //只要定義了該宏 DEBUG_PRINT就會(huì)起作用 沒有定義則不起作用
// 字符串拼接
//#define CONCAT_STR(a,b) a##b dev平臺(tái)用不了 linux未測試
#define CONCAT_STR(a,b) a b
// 條件編譯
#ifdef DEBUG
#define DEBUG_PRINT(msg) printf("Debug: %sn", msg)
#else
#define DEBUG_PRINT(msg)
#endif
int main(void)
{
printf("5的平方是%drn",SQUARE(5));
printf("MAX(2,3)返回較大的一個(gè)數(shù)是%drn",MAX(2,3)) ;
DEBUG_PRINT("調(diào)試信息");
printf("%srn", CONCAT_STR("你好", "World")); // 這里會(huì)被展開為 printf("%srn", "你好, " "World");
}
這里踩到了一個(gè)坑............. dev里這個(gè)##符號(hào)竟然不能使用!看了這個(gè)博主的文章才明白 https://blog.csdn.net/leon1741/article/details/78149881,致謝致敬
運(yùn)行結(jié)果
在這里插入圖片描述
宏定義使用注意事項(xiàng)
使用宏定義時(shí)需要注意一些事項(xiàng),以確保代碼的可讀性和正確性。以下是一些宏定義的注意事項(xiàng):
括號(hào)的使用:
在宏定義中,為了避免優(yōu)先級(jí)問題,通常在宏的參數(shù)和整體表達(dá)式外部都使用括號(hào)。例如:#define SQUARE(x) ((x) * (x))
這樣可以確保在使用時(shí)不會(huì)出現(xiàn)預(yù)期之外的行為。
避免副作用:
在宏中避免使用具有副作用的表達(dá)式,因?yàn)楹晔呛唵蔚奈谋咎鎿Q,可能導(dǎo)致意外的行為。// 避免這樣的宏定義 #define INCREMENT(x) x++
使用大寫字母:
為了與變量和函數(shù)名區(qū)分,宏的名稱通常使用大寫字母。#define MAX_SIZE 100
多行宏的注意:
如果宏跨越多行,確保在每行的末尾使用反斜杠 連接,以避免語法錯(cuò)誤。#define PRINT_SUM(a, b) do { int sum = (a) + (b); printf("Sum: %dn", sum); } while(0)
參數(shù)的使用:
宏參數(shù)的使用要小心,確保在宏展開時(shí)不會(huì)導(dǎo)致預(yù)期之外的結(jié)果。// 不要這樣使用,可能導(dǎo)致問題 #define SQUARE(x) x * x
條件編譯:
在使用條件編譯時(shí),確保相關(guān)的宏定義和取消定義都是正確的。#ifdef DEBUG // ... #endif
總體來說,清晰、簡潔、避免副作用是設(shè)計(jì)宏定義時(shí)的關(guān)鍵原則。良好的宏定義可以提高代碼的可讀性和可維護(hù)性。
在單片機(jī)中可以使用預(yù)編譯來區(qū)分代碼版本
如果定義了REG_CODE 這個(gè)宏且其結(jié)果是1那么就是寄存器版本代碼否則就是庫函數(shù)版本代碼
void LED_Config(void)
{
#if (REG_CODE)
RCC- >AHB1ENR |= 1< 2; //GPIOC的時(shí)鐘開關(guān)
GPIOC- >MODER &= ~(3< 2*4);//把89位清00 PC4
GPIOC- >MODER |= (1< 2*4);//只是把第89位置01
GPIOC- >MODER &= ~(3< 2*5);//把10 11位清00 PC5
GPIOC- >MODER |= (1< 2*5);//只是把第89位置01
GPIOC- >MODER &= ~(3< 2*6);//把11 12位清00 PC6
GPIOC- >MODER |= (1< 2*6);//只是把第89位置01
GPIOC- >MODER &= ~(3< 2*7);//把89位清00 PC7
GPIOC- >MODER |= (1< 2*7);//只是把第89位置01
GPIOC- >OTYPER &= ~(1< 4); //推挽模式//0xFFFF FFEF
GPIOC- >OTYPER &= ~(1< 5);
GPIOC- >OTYPER &= ~(1< 6);
GPIOC- >OTYPER &= ~(1< 7);
//假設(shè)輸出狀態(tài) 燈的開關(guān)
GPIOC- >ODR |= (1< 4)| (1< 5)|(1< 6) |(1< 7); //默認(rèn)全關(guān)
printf("寄存器代碼...rn");
#else
printf("LED庫函數(shù)代碼...rn");
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed;
GPIO_Init(GPIOB,&GPIO_InitStruct);
#endif
}
至此,預(yù)編譯相關(guān)的知識(shí)點(diǎn)就介紹完了。
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136685 -
源代碼
+關(guān)注
關(guān)注
96文章
2945瀏覽量
66730 -
代碼
+關(guān)注
關(guān)注
30文章
4779瀏覽量
68521 -
編譯
+關(guān)注
關(guān)注
0文章
657瀏覽量
32852 -
預(yù)處理
+關(guān)注
關(guān)注
0文章
33瀏覽量
10478
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論