C語言-宏定義#define的用法

1 不帶參宏定義

這種用法是最簡單最常見的一種方式,如下:

#define PAI 3.14

注意

  • 宏定義原則上用大寫表示,雖然這並不是規定
  • 由於宏定義是預處理指令,並非是C語言語句,所以末尾不必加分號

它的功能是在程序中若出現了PAI,就把它替換3.14,示例程序如下:

#include <stdio.h>
#define PAI 3.14 // 不帶參宏定義

int main() {
    double r = 2;
    printf("半徑爲%.2lf的圓的周長爲%.2lf", r, 2*PAI*r);
    return 0;
}

2 帶參宏定義

使用方法如下:

#define ADD(a,b) (a+b)

它的功能是計算a+b的結果,示例程序如下:

#include <stdio.h>
#define ADD(a,b) (a+b)
 
int main() {
    int a = 1;
    int b = 2;
    printf("a+b=%d", ADD(a, b));
    return 0;
}

這裏需要注意的是,我們習慣上會把後面表達式添上括號,如(a+b),在本例中去掉這個括號也是可以的,但有些情況下會出現問題,如下:

#include <stdio.h>
#define ADD(a,b) a+b
#define SUB(a,b) a-b
 
int main() {
    int a = 1;
    int b = 2;
    printf("%d", ADD(a,b)*SUB(a,b)); // ab的和與差相乘
    return 0;
}

這個程序的功能是計算a+b乘以a-b的值,實際上程序的輸出結果爲1,我們稍加思考發現本例中a+b>0a-b<0答案必然是負數,結果卻是正數,顯然出了問題,那麼再把表達式的括號加上試試看:

#define ADD(a,b) (a+b)
#define SUB(a,b) (a-b)

程序運行後輸出結果爲-3,可以口算發現此結果是正確的,出現問題的原因就要從#define預編譯指令的原理說起,在編譯一個C語言程序時,第一步執行的是預編譯這個過程中會把#define中定義的宏進行替換,如不加括號的程序中就替換成了如下:

printf("%d", a+b*a-b); // 輸出結果爲1

顯然根據數學運算規則會先算乘法後算加法,所以結果爲1,那麼加上括號的程序中替換後結果如下:

printf("%d", (1+2)*(1-2)); // 輸出結果爲-3

先算括號裏的式子,整個式子的結果顯然爲-3,通過本例可以發現爲了避免替換後出現類似這種錯誤,儘量將表達式加上括號,特別是表達式中有多個變量時

帶參宏定義和函數有點像,他們的區別如下

  • 函數參數傳遞時會計算實參的值再傳遞給形參,如執行函數func(1+2),會先計算1+2的值爲3再交給函數體,而帶參宏定義不進行任何計算,直接替換
  • 根據上面例子可以發現,帶參宏定義對數據類型沒有定義,可以使用多種合法類型帶入,但函數要根據定義函數時聲明的參數類型傳遞值
  • 帶參宏定義僅佔用預編譯的時間,而函數的執行會佔用空間和時間,如分配內存空間,入棧保留現場,返回值等

3 與字符串有關的用法

3.1 字符串轉換

使用方法如下,在s前加上#,它的作用是將傳入的s轉換爲字符串

#define STR(s) #s

示例程序如下,給出參數Wuhan jia you,最後以字符串的形式輸出來

#include <stdio.h>
#define STR(s) #s
 
int main() {
    puts(STR(Wuhan jia you));
    return 0;
}

需要注意的是,轉換的是s,而不是s裏的值,見下面兩個程序:

// 程序1
#include <stdio.h>
#define STR(s) #s
 
int main() {
    const char *s = "Wuhan jia you";
    puts(STR(s));
    return 0;
}
// 程序2
#include <stdio.h>
#define STR(s) #s
 
int main() {
    int n = 2020;
    puts(STR(n));
    return 0;
}

第一個程序輸出結果爲s,第二個程序的輸出結果爲n,可見這個用法就是你給它什麼,它就把它直接轉換爲字符串,不管它是不是變量

3.2 字符轉換

使用方法如下,在c的前面加上#@,它的作用是把c轉換爲字符

#define STR(c) #@c

注意:本用法不支持gcc編譯器,如在gcc編譯器下編譯,會出現下面的錯誤信息error: '#' is not followed by a macro parameter,這個用法僅支持微軟系列(Microsoft Specific)

示例程序如下,給出參數1,最後把1轉換爲字符1輸出:

#include <stdio.h>
#define STR(c) #@c
 
int main() {
    putchar(STR(1));
    return 0;
}

關於它的轉換規則和3.1 字符串轉換的類似

3.3 字符連接

使用方法如下,在兩個參數中間添加##,它的作用是連接前後兩個參數,把它們變成一個參數

#define CAT(a,b) a##b

示例程序如下

#include <stdio.h>
#define CAT(a,b) a##b
 
int main() {
    int n = CAT(123, 456);
    printf("%d", n);
    return 0;
}

輸出結果爲123456

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章