c 預處理的巨集定義
概念
以“#”號開頭的都是預處理命令
例如 #include <stdio.h>巨集定義
巨集定義
無引數的巨集名後不帶引數
# 表示這是一條預處理命令, define 為巨集定義命令。“識別符號”為所定義的巨集名。“字串”可以是常數,表示式、格式串等
舉例:
#define PI 3.1415926
作用:
就是用指定識別符號PI來代替數3.1415926
對源程式作編譯時, 將先由預處理程式進行巨集代換,
即用3.1415926表示式去置換所有的巨集名PI, 然後編譯
#include <stdio.h> # define PIView Code3.1415 int main(int argc, char const *argv[]) { printf("%f\n", PI); return 0; }
注意:
1. 預處理程式對巨集定義不做任何檢查,如果有錯誤,只能在編譯已被巨集展開後的源程式是發現
2. 巨集定義不是說明或語句,在行末不必加分好,如加上分好則連分號也一起置換 容易出錯的地方
3. 巨集定義必須寫在函式之外, 其作用域為巨集定義命令起到源程式結束。如要終止其作用域可
使用# undef命令
4. 巨集定義用雙引號括起來的都是常量字串 例如“PI” 則列印PI
5. 巨集定義允許巢狀, 在巨集定義的字串中,可以使用已定義的巨集名。在巨集展開時由預處理程式層層代換。
6. 習慣上巨集定義用大寫字母表示, 以便區分
#include <stdio.h> # define PI 3.1415 # define S PI*r*r int main(int argc, char const *argv[]) { double s; int r; scanf("%d", &r); s = S; printf(View Code"%d\n", s); return 0; }
7. 可用巨集定義表示資料型別, 是書寫方便
# define INTEGER int
8. 對“輸出格式”作巨集定義, 可以縮減書寫麻煩
#include <stdio.h> # define P printf # define D "%d\n" int main(int argc, char const *argv[]) { p(D, 1); }
define 和typeof的區別
巨集定義 只是簡單的字串代換, 是預處理完成的。
typedef 是在編譯時處理的, 它不是作簡單的代換, 而是對型別說明符重新命名。被命名的識別符號具有型別定義說明的功能。
typedef 相當於型別重新命名
#include <stdio.h> #define PIN1 char* typedef char* PIN2; int main(int argc, char const *argv[]) { PIN1 x, y; // char* x, y;也就是 char *x, y PIN2 a, b; // char* a, b; char *a, *b; printf("%d %d\n", sizeof(x), sizeof(y)); printf("%d %d\n", sizeof(a), sizeof(b)); //結果: // 8 1 //8 8 }
帶引數巨集定義
c語言允許巨集帶有引數, 在巨集定義中的引數成為形式引數, 在巨集呼叫中的引數成為實際引數。
對帶引數的紅,在呼叫中, 不僅要展開,而且要用實參去代替形參
帶參巨集定義的一般形式為:
# define 巨集名(形參表) 字串
帶參巨集呼叫的一般形式為: 巨集名(實參表)
例如:
#define M(y) y*y+3*y /*巨集定義*/ 。。 k=M(5); /*巨集呼叫*/ 相當於k = 5*5 + 3*5 會直接替換,沒有預處理的過程
看例子
#include <stdio.h> #define MAX(a, b) (a, b)?a:b int main(int argc, char const *argv[]) { int x, y, max; scanf("%d %d", &x, &y); max = MAX(x, y); printf("%d\n", max); return 0; }
注意:
首先win程式設計裡面都是巨集定義
1. 帶參巨集定義中,巨集名和形參表之間不能有空格出現
例如:
正確: #define MAX(a, b) (a>b)?a:b 錯誤: #define MAX (a, b) (a>b)?a:b
2. 在帶參巨集定義中,形式引數不分配記憶體單元, 因此不必作型別定義。
而巨集呼叫中的實參有具體的值。要用他們去代換形參, 因此必須作型別說明
3. 在巨集定義中的形參是識別符號, 而巨集呼叫中的實參可以是表示式。
4. 在巨集定義中, 字串內的形參通常要用括號括起來以避免出錯。
例如 # define M(y) (y)^(y)表示式的y都用括號括起來, 因此結果是正確的。
如果去掉括號, 把程式改成一下形式,那麼程式的結果不是你想要的結果
注意:
#define S(y) (y)*(y) ..... sq = 160 / S(3) //等於160 / (y)*(y) 需要更改成 #define S(y) ((y)*(y))
5. 帶參巨集和帶參函式很相似, 但有本質上的不同, 除上面已談到的各點外,
把同一表示式用函式處理與用巨集處理兩者的結果有可能是不同的。
稍等例子,明天測試
6. 巨集定義也可以定義多個語句, 在巨集呼叫時, 把這些語句又代換到源程式內。
#include <string.h>
# define S(s1, s2) strcat(s1, s2) //strcat 類似連線,或合併
巨集定義的if
條件編譯三種形式:
1. #ifdef 識別符號
程式段1
#else
程式段2
#endif
2. #ifndef 識別符號
程式段1
#else
程式段2
#endif
3.#if 常量表達式
程式段1
#else
程式段2
#endif
相關推薦
編譯器、作業系統、CPU相關的預處理巨集定義
疑問一、How to list compiler predefined macros? 編譯器預處理巨集定義用途: 參考: http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_pr
C/C++預處理、巨集定義--你和大牛之間只差一個巨集定義#define
今天讀一個github上下載的C語言程式碼,讀得時候就像在讀天書,完全不像C。在此之前,我一直以為自己C語言掌握的還不錯的。所以惡補了以下關於預處理的知識。 相信很多讀者和我一樣,只是會用C語言而已,只會迴圈跳躍閉著眼,但是學了巨集定義之後就馬上可以走上人生巔峰了。廢話到此為止,下面開整: 引用經
c 預處理的巨集定義
概念 以“#”號開頭的都是預處理命令 例如 #include <stdio.h>巨集定義 巨集定義無引數的巨集名後不帶引數# 表示這是一條預處理命令, define 為巨集定義命令。“識別符號”為所定義的巨集名。“字串”可以是常數,表示式、格式串等 舉例: #define P
C中的預編譯巨集定義
在將一個C源程式轉換為可執行程式的過程中, 編譯預處理是最初的步驟. 這一步驟是由前處理器(preprocessor)來完成的. 在源流程式被編譯器處理之前, 前處理器首
C++預處理、巨集
一、C++編譯過程從C++原始檔到可執行檔案的編譯過程,有如下幾個步驟,g++提供了很多編譯選項,可以讓我們控制整個編譯過程:預處理(g++選項 -E):預處理就是本文要詳細說的巨集替換、標頭檔案包含等
c/c++預處理過程詳解(二)之條件編譯及預定義的巨集
未經博主同意不得私自轉載!不準各種形式的貼上複製本文及盜圖! 首先對於上篇文章中巨集定義的補充: (1)#define NAME"zhangyuncong" 程式中有"NAME"則,它會不會被替換呢? (2)#define 0x abcd 可以嗎?也就是說,可不可以用不是
C++預處理命令#define巨集(macro)展開的若干用法
提及#define,你會不會馬上聯想到自己時時用#define MAX 100用於標記一個數組的長度?這樣做無非兩個原因,一來,#define是編譯時的巨集展開,對執行時間毫無影響。其二,使用諸如MAX這類見名知其意的識別符號代替生硬的數學符號使程式更
c#如何處理自定義消息
span 只供參考 dto win32 使用 void font 示例 截取 C#自定義消息通信往往采用事件驅動的方式實現,但有時候我們不得不采用操作系統的消息通信機制,例如在和底層語言開發的DLL交互時,是比較方便的。下面列舉了一些實現方式,以供參考。有
C/C++預處理指令#define,條件編譯#ifdefine
明顯 int 生效 cpp 這樣的 ffffff 給定 ron fde 本文主要記錄了C/C++預處理指令,常見的預處理指令如下: #空指令,無任何效果 #include包含一個源代碼文件 #define定義宏 #undef取消已定義的宏 #if如果給定條件為真,則編譯下面
c++ 預處理指令#define, #endif...
第一個 ++ 空白字符 當前 def windows 源代碼 定義宏 else 常見的預處理指令有: # 空指令,無任何效果 # include 包含一個源代碼文件 #define 定義宏 #undef 取消已定義的宏 #if 如果給定條件為真,則編譯下面代碼 #ifdef
C# 預處理指令
app processor framework war 配置 data- sys app1 RoCE C# 預處理指令 #if...else #define...undef #warning #error #pragma #pragma checksum
C語言開關巨集定義的學習##__VA_ARGS__
最近寫c程式,學到一種開關巨集,極大提高程式的控制性: #define __DEBUG #ifdef __DEBUG #define tnfs_print(format, ...) printf (format, ##__VA_ARGS__) #else #define tnfs_print
c預處理命令偏門知識
1.預處理替換 #define max(x,y) ((x)>(y)?(x):(y))用來代替函式 2.預處理代替列印 #define print(A) printf("%s=%d",#A,A)用來將識別符號及其所代表的數值打印出來 3.預處理連線符 #defin
C/C++中標準巨集定義及其用法
ANSI C標準中有幾個標準預定義巨集 __func__:在原始碼中插入當前所在函式名; __LINE__:在原始碼中插入當前原始碼行號; __FILE__:在原始檔中插入當前原始檔名; __DATE__:在原始檔中插入當前的編譯日期 __TIME__:在原始檔
如何通過 讀取配置引數 而不是 預編譯 巨集定義方式 來決定是否執行printf函式
在一個專案中,本來開始決定通過巨集定義方式來決定是否進行 printf 列印除錯資訊的,但後面考慮到使用配置引數的方式應該更好,因為通過巨集定義方式,還需要再編譯一遍程式才能進行顯示,而通過讀取配置引數方式,只需要在配置檔案中更改配置項即可,這樣更符合實際需要。 大致思路:先將需要列
【C語言】巨集定義define 和型別重新命名typedef
C語言裡面有兩個不容易區分的語法概念,巨集定義define 和型別重新命名typedef。下面我們來談一下兩者之間的差異。 1.型別重新命名typedef: 關鍵字typedef提供了一種為已定義好的資料型別建立別名的機制,為了建立更簡短的型別名,通常使用type
C++---C/C++預處理指令#define,#ifdef,#ifndef,#endif
本文主要記錄了C/C++預處理指令,常見的預處理指令如下: #空指令,無任何效果 #include包含一個原始碼檔案 #define定義巨集 #undef取消已定義的巨集 #if如果給定條件為真,則編譯下面程式碼 #ifdef如果巨集已經定義,則編譯下面程式碼
C語言中巨集定義和函式的取捨
原文連結:http://www.embedu.org/Column/Column177.htm 要寫好C語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高程式碼的可移植性和可讀性等。 在軟體開發過程中,經常有一些常用或者通用的功能或者程式碼段,這些功能既可以寫成函式,也可以
C語言應用巨集定義解決三角形的面積問題
#include <stdio.h> #include<math.h> #define s(a,b,c) ((0.5)*((a)+(b)+(c))) #define area(s,a,b,c) sqrt((s)*((s)-(a))*((s
C++預處理(二) —— #define
文章目錄 #define 定義一個符號 #define 定義巨集 1. 給替換變數加引號 2. 在巨集表示式中連線幾個引數 3. 邏輯前處理器指令 #define與if條件語句靈活運用