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語言(巨集定義)C語言
- 【C進階】21、巨集定義與使用分析
- C語言巨集定義##連線符和#符的使用C語言
- C/C++語言巨集定義##連線符和符#的使用C++
- C語言學習第8篇---位運算子使用探究C語言
- C語言巨集定義中#define中的井號#的使用C語言
- c語言巨集的使用C語言
- C語言-->(十四)結構體、巨集、編譯C語言結構體編譯
- C 語言巨集定義 #define 的理解與資料整理
- doxygen 宏定義/宏編譯/條件編譯/預處理/預編譯 不處理、忽略條件、分析所有條件、滿足所有條件的方法編譯
- C語言的條件編譯#if, #elif, #else, #endif、#ifdef, #ifndefC語言編譯
- 條件編輯及宏定義學習小結
- 【C進階】22、條件編譯分析編譯
- c++進階(一)C語言條件編譯及編譯預處理階段C++C語言編譯
- 一個C++巨集定義與列舉定義重複的編譯錯誤C++編譯
- 使用 Sublime Text 3 編譯 C 語言編譯
- PLSQL Language Reference-PL/SQL語言基礎-條件編譯-條件編譯指令限制SQL編譯
- PLSQL Language Reference-PL/SQL語言基礎-條件編譯-條件編譯舉例SQL編譯
- 有關C語言的知識---巨集定義用法C語言
- C語言基礎-2、函式的定義與使用C語言函式
- C語言零基礎教程之預處理和巨集定義篇C語言
- Solidity語言學習筆記————2、使用編譯器Solid筆記編譯
- 第3天:定義語言編碼(轉)
- c語言的定義與宣告C語言
- 在命令列中使用 msbuild 定義多個編譯條件 DefineConstants 時出錯命令列UI編譯
- C#特性學習與使用(為列舉定義Description)C#
- 使用ant巨集定義任務
- Rust 交叉編譯與條件編譯總結Rust編譯
- C語言的本質(19)——預處理之一:巨集定義C語言
- C語言編譯工具C語言編譯
- 前端學習(2366):條件編譯跨端相容前端編譯跨端
- 使用PHP實現詞法分析與自定義語言PHP詞法分析
- gcc編譯階段列印巨集定義的內容GC編譯
- C++巨集定義#defineC++
- java編譯、編碼、語言設定Java編譯
- 為什麼要學習和使用C語言?C語言
- Rust 條件編譯Rust編譯