C語言必備知識編譯預處理
編譯預處理就是在編譯源代碼之前進行的一系列處理,將源程序中的一些特殊命令進行展開或處理,生成擴展的源代碼。這些特殊命令通常以“#”開頭,占單獨的行,語句尾部不需要加分號。
宏定義
(#define)是一種常見的編譯預處理指令,用于定義宏,實現代碼的簡化和重用。
文件包含(#include)用于在源文件中引入其他文件的內容,方便代碼模塊化和復用。
條件編譯
(#if, #else, #endif等)允許根據條件選擇性地編譯部分代碼,提高代碼的靈活性。
在預處理階段,這些指令會被解釋和處理,生成經過預處理的源代碼,然后再經過編譯、匯編、鏈接等步驟生成最終的可執行文件。這個過程有助于提高代碼的可維護性和可移植性。
書寫格式
以“#”開頭、占單獨行、語句尾不加分號。這樣的規范有助于編譯器正確解釋和處理這些指令,同時也使得代碼更加清晰易讀。這樣的一致性規范有助于維護代碼時的可讀性和可理解性。
宏定義的例子
// 定義常量
#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就會起作用 沒有定義則不起作用
// 字符串拼接
//#define CONCAT_STR(a,b) a##b dev平臺用不了 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)返回較大的一個數是%drn",MAX(2,3)) ;
DEBUG_PRINT("調試信息");
printf("%srn", CONCAT_STR("你好", "World")); // 這里會被展開為 printf("%srn", "你好, " "World");
}
這里踩到了一個坑............. dev里這個##符號竟然不能使用!看了這個博主的文章才明白 https://blog.csdn.net/leon1741/article/details/78149881,致謝致敬
運行結果
在這里插入圖片描述
宏定義使用注意事項
使用宏定義時需要注意一些事項,以確保代碼的可讀性和正確性。以下是一些宏定義的注意事項:
括號的使用:
在宏定義中,為了避免優先級問題,通常在宏的參數和整體表達式外部都使用括號。例如:#define SQUARE(x) ((x) * (x))
這樣可以確保在使用時不會出現預期之外的行為。
避免副作用:
在宏中避免使用具有副作用的表達式,因為宏是簡單的文本替換,可能導致意外的行為。// 避免這樣的宏定義 #define INCREMENT(x) x++
使用大寫字母:
為了與變量和函數名區分,宏的名稱通常使用大寫字母。#define MAX_SIZE 100
多行宏的注意:
如果宏跨越多行,確保在每行的末尾使用反斜杠 連接,以避免語法錯誤。#define PRINT_SUM(a, b) do { int sum = (a) + (b); printf("Sum: %dn", sum); } while(0)
參數的使用:
宏參數的使用要小心,確保在宏展開時不會導致預期之外的結果。// 不要這樣使用,可能導致問題 #define SQUARE(x) x * x
條件編譯:
在使用條件編譯時,確保相關的宏定義和取消定義都是正確的。#ifdef DEBUG // ... #endif
總體來說,清晰、簡潔、避免副作用是設計宏定義時的關鍵原則。良好的宏定義可以提高代碼的可讀性和可維護性。
在單片機中可以使用預編譯來區分代碼版本
如果定義了REG_CODE 這個宏且其結果是1那么就是寄存器版本代碼否則就是庫函數版本代碼
void LED_Config(void)
{
#if (REG_CODE)
RCC- >AHB1ENR |= 1< 2; //GPIOC的時鐘開關
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);
//假設輸出狀態 燈的開關
GPIOC- >ODR |= (1< 4)| (1< 5)|(1< 6) |(1< 7); //默認全關
printf("寄存器代碼...rn");
#else
printf("LED庫函數代碼...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
}
至此,預編譯相關的知識點就介紹完了。
-
C語言
+關注
關注
180文章
7615瀏覽量
137827 -
源代碼
+關注
關注
96文章
2946瀏覽量
66989 -
代碼
+關注
關注
30文章
4836瀏覽量
69119 -
編譯
+關注
關注
0文章
662瀏覽量
33067 -
預處理
+關注
關注
0文章
33瀏覽量
10514
發布評論請先 登錄
相關推薦
介紹一下C語言的預處理知識與宏定義原理
C語言的編譯預處理
C語言程序設計教程之如何進行函數與編譯預處理資料概述
![<b class='flag-5'>C</b><b class='flag-5'>語言</b>程序設計教程之如何進行函數與<b class='flag-5'>編譯</b><b class='flag-5'>預處理</b>資料概述](https://file.elecfans.com/web1/M00/7E/45/pIYBAFwOMl2AC2iFAAAyixa3t3Q061.png)
C語言程序設計教程之編譯預處理的詳細資料說明
![<b class='flag-5'>C</b><b class='flag-5'>語言</b>程序設計教程之<b class='flag-5'>編譯</b><b class='flag-5'>預處理</b>的詳細資料說明](https://file.elecfans.com/web1/M00/81/F8/pIYBAFw0RFqAfQ8HAAWUkUKmUAA352.png)
淺析VerilogHDL編譯系統的預處理
C語言宏定義與預處理、函數和函數庫
![<b class='flag-5'>C</b><b class='flag-5'>語言</b>宏定義與<b class='flag-5'>預處理</b>、函數和函數庫](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論