1. 程式人生 > >c 預處理的巨集定義

c 預處理的巨集定義

概念

以“#”號開頭的都是預處理命令

例如 #include <stdio.h>巨集定義

巨集定義
無引數的巨集名後不帶引數
# 表示這是一條預處理命令, define 為巨集定義命令。“識別符號”為所定義的巨集名。“字串”可以是常數,表示式、格式串等

舉例:

#define PI 3.1415926

作用:

就是用指定識別符號PI來代替數3.1415926
對源程式作編譯時, 將先由預處理程式進行巨集代換,
即用3.1415926表示式去置換所有的巨集名PI, 然後編譯

#include <stdio.h>

# define PI 
3.1415 int main(int argc, char const *argv[]) { printf("%f\n", PI); return 0; }
View Code

注意: 

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(
"%d\n", s); return 0; }
View Code

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條件語句靈活運用