C語言學習第18篇---巨集定義與使用 / 條件編譯使用分析
知識來源主要是陳正衝老師的《C語言深度解剖》及Delphi Tang老師的《C語言剖析》,有興趣的朋友可以看我置頂文章獲取
C語言中的巨集定義
#define是前處理器處理的單元實體之一
#define定義的可以出現在程式的任意位置
#define定義之後的程式碼都可以使用這個巨集
C語言中的巨集常量
#define定義的巨集常量可以直接使用
#define定義的巨集常量本質為字面量
例項1:巨集定義分析
#define ERROR -1
#define PATH1 "D:\test\test.c"
#define PATH2 D:\test\test.c
#define PATH3 D:\test\
test.c
int main()
{
int err = ERROR;
char* p1 = PATH1;
char* p2 = PATH2;
char* p3 = PATH3;
}
巨集定義的表示式:
#define表示式的使用類似函式呼叫
#define表示式可以比函式更加強大
#define變大師比函式更容易出錯
實驗2:巨集表示式分析
// #include <stdio.h>
#define _SUM_(a, b) (a) + (b)
#define _MIN_(a, b) ((a) < (b) ? (a) : (b))
#define _DIM_(a) sizeof(a)/sizeof(*a)
int main()
{
int a = 1;
int b = 2;
int c[4] = {0};
int s1 = _SUM_(a, b);
int s2 = _SUM_(a, b) * _SUM_(a, b);
int m = _MIN_(a++, b);
int d = _DIM_(c);
// printf("s1 = %d\n", s1);
// printf("s2 = %d\n", s2);
// printf("m = %d\n", m);
// printf("d = %d\n", d);
return 0;
}
巨集表示式與函式的對比:
巨集表示式杯前處理器處理,編譯器不知道巨集表示式的存在
巨集表示式用“實參”完全代替形參,不進行任何運算
巨集表示式沒有任何的“呼叫”開銷
巨集表示式中不能出現遞迴定義
強大的內建巨集:
實驗4:巨集使用綜合
#include <stdio.h>
#include <malloc.h>
#define MALLOC(type, x) (type*)malloc(sizeof(type)*x)
#define FREE(p) (free(p), p=NULL)
#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s)
#define FOREACH(i, m) for(i=0; i<m; i++)
#define BEGIN {
#define END }
int main()
{
int x = 0;
int* p = MALLOC(int, 5);
LOG("Begin to run main code...");
FOREACH(x, 5)
BEGIN
p[x] = x;
END
FOREACH(x, 5)
BEGIN
printf("%d\n", p[x]);
END
FREE(p);
LOG("End");
return 0;
}
條件編譯的基本概念:
條件編譯的行為類似於C語言中的if ... else...
條件編譯時預編譯指示命令,用於控制是否編譯某段程式碼(這也是專案中經常用到的)
條件編譯例項:
// #include <stdio.h>
#define C 1
int main()
{
const char* s;
#if( C == 1 )
s = "This is first printf...\n";
#else
s = "This is second printf...\n";
#endif
// printf("%s", s);
return 0;
}
條件編譯的本質:
預編譯器根據條件編譯指令有選擇的刪除程式碼
編譯器不知道程式碼分支的存在
if ... else ... 語句在執行期進行分支判斷
條件編譯指令在預編譯期進行分支判斷
可以通過命令列定義巨集
gcc -Dmacro = value file.c
或者
gcc -Dmacro file.c
實驗:通過命令列定義巨集
//#include <stdio.h>
int main()
{
const char* s;
#ifdef C
s = "This is first printf...\n";
#else
s = "This is second printf...\n";
#endif
//printf("%s", s);
return 0;
}
#include的本質
#include的本質是將已經存在的檔案內容嵌入到當前檔案中
#include的間接包含會產生嵌入檔案內容的操作
條件編譯使用例項;
global.h
// global.h
#ifndef _GLOBAL_H_
#define _GLOBAL_H_
int global = 10;
#endif
test.h
// test.h
#ifndef _TEST_H_
#define _TEST_H_
#include "global.h"const char* NAME = "test.h";char* hello_world(){ return "Hello world!\n";}
#endif
// #include <stdio.h>
#include "test.h"
#include "global.h"
int main()
{
const char* s = hello_world();
int g = global;
// printf("%s\n", NAME);
// printf("%d\n", g);
return 0;
}
條件編譯可以解決標頭檔案重複包含的編譯錯誤
條件編譯的意義:
條件編譯使得我們可以按照不同的條件編譯不同的程式碼段,因而可以產生不同的目的碼
#if... #else #endif 被預編譯器處理,而 if ... else ...語句被編譯器處理,必然被編譯進目的碼
實際工程中條件編譯主要用於以下兩種情況
不同的產品線公用一份程式碼
區分編譯產品的除錯版和釋出版
例項分析 產品線區分及除錯程式碼應用
product.h
#define DEBUG 1
#define HIGH 1
#include <stdio.h>
#include "product.h"
#if DEBUG
#define LOG(s) printf("[%s:%d] %s\n", __FILE__, __LINE__, s)
#else
#define LOG(s) NULL
#endif
#if HIGH
void f()
{
printf("This is the high level product!\n");
}
#else
void f()
{
}
#endif
int main()
{
LOG("Enter main() ...");
f();
printf("1. Query Information.\n");
printf("2. Record Information.\n");
printf("3. Delete Information.\n");
#if HIGH
printf("4. High Level Query.\n");
printf("5. Mannul Service.\n");
printf("6. Exit.\n");
#else
printf("4. Exit.\n");
#endif
LOG("Exit main() ...");
return 0;
}
小結:
相關文章
- C語言 - 條件編譯C語言編譯
- 【C進階】21、巨集定義與使用分析
- C語言巨集定義中#define中的井號#的使用C語言
- c語言巨集的使用C語言
- C語言-->(十四)結構體、巨集、編譯C語言結構體編譯
- doxygen 宏定義/宏編譯/條件編譯/預處理/預編譯 不處理、忽略條件、分析所有條件、滿足所有條件的方法編譯
- 【C進階】22、條件編譯分析編譯
- 使用 Sublime Text 3 編譯 C 語言編譯
- 條件編輯及宏定義學習小結
- Solidity語言學習筆記————2、使用編譯器Solid筆記編譯
- C語言基礎-2、函式的定義與使用C語言函式
- 在命令列中使用 msbuild 定義多個編譯條件 DefineConstants 時出錯命令列UI編譯
- c語言的定義與宣告C語言
- 前端學習(2366):條件編譯跨端相容前端編譯跨端
- Rust 交叉編譯與條件編譯總結Rust編譯
- 使用PHP實現詞法分析與自定義語言PHP詞法分析
- gcc編譯階段列印巨集定義的內容GC編譯
- Rust 條件編譯Rust編譯
- C語言零基礎教程之預處理和巨集定義篇C語言
- c 語言中巨集定義和定義全域性變數的區別變數
- C語言學習方法,怎麼學習C語言?C語言
- c語言多檔案編譯C語言編譯
- 學習Rust 條件語句Rust
- 0x03. 使用巨集定義事件事件
- 編譯型語言與解釋型語言編譯
- 在 C 中引用匯編語言定義的 .globl 變數變數
- Go語言ORM包:使用worm構造查詢條件GoWorm
- makefile--if條件判斷語句的語法與使用
- C++ | VS2017 C++專案配置使用的常見巨集定義C++
- 小C語言--詞法分析程式(編譯原理實驗一)C語言詞法分析編譯原理
- 3- C語言編譯過程C語言編譯
- C語言編譯器手機版C語言編譯
- C語言中的標頭檔案中的巨集定義C語言
- 010 Rust 非同步程式設計,使用 select 巨集的條件Rust非同步程式設計
- uni-app 條件編譯APP編譯
- C語言學習之:指標與字串C語言指標字串
- C++中使用巨集定義來註釋掉所有的cout輸出C++
- C語言巨集中"#"和"##"的用法C語言