C語言進(jìn)階(預(yù)處理命令詳解)
1.宏定義
1.1不帶參宏
#define PI 3.14
變量名盡量大寫
1.2帶參宏
定義方式:
#define MAX(x, y) x > y ? x : y
下面的代碼運(yùn)行結(jié)果為15,顯然是錯(cuò)誤的。
#include <stdio.h>
#define JISUAN(x, y, z) x * y + z
int main(void)
{
int a = 0;
a = JISUAN(1 + 2,2 * 3,3 - 1);
printf("%d",a);
} 給變量帶上括號(hào),運(yùn)行結(jié)果是,正確做法如下:運(yùn)行結(jié)果為20。因此盡量給定義添加括號(hào)。避免計(jì)算錯(cuò)誤。
#include <stdio.h>
#define JISUAN(x, y, z) ((x) * (y) + (z))
int main(void)
{
int a = 0;
a = JISUAN(1 + 2,2 * 3,3 - 1);
printf("%d",a);
} 帶參宏和函數(shù)的區(qū)別:
| 帶參宏 | 函數(shù) |
| 帶參宏沒有參數(shù)類型、返回值、函數(shù)類型 相關(guān)概念 | 函數(shù)有參數(shù)類型、函數(shù)類型、返回值相關(guān) 概念 |
| 帶參宏只是代碼的替換,沒有調(diào)用傳參過 程 | 函數(shù)有調(diào)用、傳參過程 |
| 帶參宏是在程序編譯時(shí)展開,代碼體積增 大 | 函數(shù)是在程序運(yùn)行過程中加載,代碼體積 不會(huì)增大 |
| 帶參宏沒有傳參過程,執(zhí)行效率高 | 函數(shù)有傳參過程,需要調(diào)用、傳參產(chǎn)生資 源開銷 |
| 簡(jiǎn)單的代碼想要封裝模塊,優(yōu)先帶參宏 | 需要嚴(yán)謹(jǐn)?shù)拇a邏輯,多行代碼,考慮使 用函數(shù) |
2.頭文件的包含
#include <stdio.h> #include <string.h> #include <math.h> #include "head.h"
#include 包含一個(gè)文件,文件會(huì)在預(yù)處理編譯時(shí)展開。
<>:在系統(tǒng)目錄下查找該頭文件。
"":在當(dāng)前目錄下查找該頭文件,如果找不到再到系統(tǒng)目錄下查找頭文件。
2.1頭文件中的內(nèi)容
1.構(gòu)造數(shù)據(jù)類型的定義
2.全局變量的聲明
3.全局函數(shù)的聲明
4.宏定義
2.2工程結(jié)構(gòu)

main.c中負(fù)責(zé)主函數(shù)編寫
- 功能代碼.c中主要負(fù)責(zé)功能函數(shù)的編寫
- 功能代碼.h中主要負(fù)責(zé)聲明功能代碼.c中編寫的功能函數(shù)
- 調(diào)用函數(shù)的文件只需加對(duì)應(yīng)函數(shù)的.h頭文件即可使用該函數(shù)
這么說可能有些不太好理解,我們來舉個(gè)例子吧:
我們先創(chuàng)建一個(gè)工程文件夾jisuan來進(jìn)行輸入兩個(gè)數(shù)字的四則運(yùn)算:

再在里面創(chuàng)建jia.c jia.h jian.c jian.h cheng.c cheng.h chu.c chu.h main.c,一個(gè).c的功能文件必須對(duì)應(yīng)一個(gè).h的頭文件聲明用來方便主文件的調(diào)用!這里main.c不需要頭文件。因?yàn)檫@里存放主函數(shù)。

創(chuàng)建好后分別對(duì)jia.cjian.c cheng.c chu.c函數(shù)進(jìn)行編寫。
- jia.c:
#include<stdio.h>
float jia(float x , float y)
{
return x + y;
}
- jian.c:
#include <stdio.h>
float jian(float x , float y)
{
return x - y;
}
- cheng.c:
#include<stdio.h>
float cheng(float x , float y)
{
return x * y;
}- chu.c:
#include<stdio.h>
extern float chu(float x , float y)
{
return x / y;
}
接下來依次編寫他們的頭文件:
- jia.h
extern float jia(float x ,float y);
jian.h
extern float jian(float x ,float y);
- cheng.h
extern float cheng(float x ,float y);
- chu.h
extern float chu(float x ,float y);
最后我們進(jìn)行主函數(shù)的編寫:這里要注意一定要用#include"函數(shù)功能.h"來聲明定義的變量
- main.c:
#include<stdio.h>
#include"jia.h"
#include"jian.h"
#include"cheng.h"
#include"chu.h"
int main(void)
{
float r1 = 0;
float r2 = 0;
float r3 = 0;
float r4 = 0;
float a = 0;
float b = 0;
scanf("%f %f",&a,&b);
r1 = jia(a,b);
r2 = jian(a,b);
r3 = cheng(a,b);
r4 = chu(a,b);
printf("jia = %f\n",r1);
printf("jian = %f\n",r2);
printf("cheng = %f\n",r3);
printf("chu = %f\n",r4);
return 0;
} ok,編寫工作完成,我們來對(duì).c文件進(jìn)行編譯:

編譯完成后就會(huì)出現(xiàn)一個(gè)可執(zhí)行文件main

我們?cè)囍\(yùn)行一下:

輸入12和45,得出計(jì)算結(jié)果。
這里,我在想這不是跟我前一篇寫的函數(shù)里extern外部聲明一樣的嘛,只不過通過#include""展開函數(shù)聲明而已。但是在未來的項(xiàng)目中撰寫每個(gè)功能代碼和主函數(shù)的不是同一個(gè)人,為了方便撰寫主函數(shù)的人調(diào)用,采用這樣的方法是不錯(cuò)的選擇。
3.條件編譯
| 關(guān)鍵字 | 功能描述 |
| #if | 如果條件為真則編譯后續(xù)代碼塊 |
| #elif | 若前面的#if或#elif條件不成立,并且該條件成立,則編譯該部分的后續(xù)代碼塊 |
| #else | 若前面的#if和#elif都不成立,則編譯該部分代碼塊 |
| #endif | 結(jié)束一個(gè)條件編譯塊,必須要與#if,#ifdef,#ifndef聯(lián)用 |
| #ifdef | 若某個(gè)宏被定義,則使用該部分代碼 |
| #ifndef | 若某個(gè)宏沒被定義,則使用該部分代碼 |
#if 1 編譯此部分 #elif 不編譯該部分 #else
#if 0 不編譯該部分 #elif 1 編譯該部分 #else test
#if 0 不編譯該部分 #elif 0 不編譯該部分 #else 編譯該部分
#if 1 編譯該部分 #endif 結(jié)束此條件編譯
#if 0 不編譯該部分 #endif 結(jié)束此條件編譯
#ifdef與#ifndef一般在項(xiàng)目測(cè)試中使用,可以在編譯時(shí)于外部定義或不定義某個(gè)宏,以此來調(diào)用代碼。
#include <stdio.h>
#define JISUAN(x, y, z) ((x) * (y) + (z))
int main(void)
{
#ifdef TEST
printf("測(cè)試\n");
#endif
#ifdef YINGYONG
printf("應(yīng)用\n");
#endif
return 0;
} 如上述代碼,對(duì)其編譯gcc -D TEST l.c -o l 在編譯的時(shí)候在外部定義了TEST,則輸出測(cè)試

如果在外部定義YINGYONG 則輸出應(yīng)用。

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
在Visual Studio Code中配置C++編譯環(huán)境的問題
關(guān)于Visual Studio Code對(duì)C++環(huán)境的配置方法應(yīng)該有好多種,我這里用到了其中的兩種,具體內(nèi)容詳情文中給大家詳細(xì)介紹,對(duì)Visual Studio Code配置C++編譯環(huán)境相關(guān)知識(shí)感興趣的朋友一起看看吧2021-07-07
C++中CSimpleList的實(shí)現(xiàn)與測(cè)試實(shí)例
這篇文章主要介紹了C++中CSimpleList的實(shí)現(xiàn)與測(cè)試實(shí)例,較為詳細(xì)的講述了C++列表類的實(shí)現(xiàn)方法,需要的朋友可以參考下2014-10-10
C++函數(shù)pyrUp和pyrDown來實(shí)現(xiàn)圖像金字塔功能
這篇文章主要介紹了C++函數(shù)pyrUp和pyrDown來實(shí)現(xiàn)圖像金字塔功能,如何使用OpenCV函數(shù) pyrUp 和 pyrDown 對(duì)圖像進(jìn)行向上和向下采樣,需要的朋友可以參考下2017-03-03
C++控制臺(tái)循環(huán)鏈表實(shí)現(xiàn)貪吃蛇
這篇文章主要為大家詳細(xì)介紹了C++控制臺(tái)循環(huán)鏈表實(shí)現(xiàn)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04

