首頁 > 軟體

C語言中#define在多行宏定義出錯的原因及分析

2023-02-25 06:01:20

C語言中#define在多行宏定義出錯的原因

1.第一種錯誤

#include<stdio.h>
#define echange(a,b) {/*宏定義中允許包含多行命令的情形,此時必須在最右邊加上""*/
 int t;
 t=a;
 a=b;
 b=t;
}
main()
{
 int c, d;
 c = 2;
 d = 3;
 printf("%d %dn", c, d);
 echange(c,d)
 printf("%d %dn", c, d);
 return 0;
}

在用#define進行多行宏定義時,註釋要放在""之前

2.第二種錯誤

#include<stdio.h>
#define echange(a,b) {/*宏定義中允許包含兩道衣裳命令的情形,此時必須在最右邊加上""*/
 int t;
 t=a;
 a=b;
 b=t;
}/*在最後一行多加了一個""*/
main()
{
 int c, d;
 c = 2;
 d = 3;
 printf("%d %dn", c, d);
 echange(c,d)
 printf("%d %dn", c, d);
 return 0;
}

在用#define進行多行宏定義時,在最後一行加上"“,我們使用#define進行多行定義時,預設最後一個”“的下一行也屬於宏定義範圍,去掉最後一行的”"即可

以下是程式碼的正確形式

#include<stdio.h>
#define echange(a,b) {/*宏定義中允許包含兩道衣裳命令的情形,此時必須在最右邊加上""*/
 int t;
 t=a;
 a=b;
 b=t;
}
main()
{
 int c, d;
 c = 2;
 d = 3;
 printf("%d %dn", c, d);
 echange(c,d)
 printf("%d %dn", c, d);
 return 0;
}

使用#define宏定義的幾個小技巧

1.偵錯開關

有時候編寫程式時為方便查詢錯誤,會在很多地方加上串列埠列印語句直觀檢視程式哪裡出錯。

但是,串列埠的輸出是需要時間的,在專案基本完成時,就需要將這些列印關閉,但是一行一行的註釋掉費時費力,不現實。

這時可以使用宏來當做一個"開關",直接操作這個宏就可以實現列印的開關,例如:

//#define    DEBUG(...)
#define        DEBUG    printf

另外,還可以使用幾個預定義的宏進行輔助:

__FILE__            // 檔案
__FUNCTION__        // 函數
__LINE__            // 行號

DEBUG("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);

2.條件編譯

當程式為了適配更多不同的環境時,還可以使用條件宏來選擇不同的程式碼模組:

#if 1
    printf("Hello!n");
#else
    printf("Hi!n");
#endif

3.宏實現函數

交換兩個數:

#define swap(a,b)     ((a)=(a)+(b);(b)=(a)-(b);(a)=(a)-(b))

比較兩個數並且返回最小的數:

#define MIN(a,b)     ((a)<(b)?(a):(b))

求陣列元素個數:

#define LENGTH(array)    (sizeof(array) / sizeof(array[0]))

4.跨行宏定義

#define    SWAP(a,b)    do { 
                        int t = 0;
                        t = a; 
                        a = b; 
                        b = t; 
                    } while(0)

細心的你可能已經注意到以上宏末尾都沒有帶分號“;”

5.防止標頭檔案被重複包含

#ifndef __TEST_H 
#define __TEST_H 
    // 標頭檔案內容 
#endif

6.帶參宏與帶參函數的區別

  • 1.宏會在編譯器在對原始碼進行編譯的時候進行簡單替換,不會進行任何邏輯檢測,即簡單程式碼複製而已;
  • 2.宏進行定義時不會考慮引數的型別;
  • 3.引數宏的使用會使具有同一作用的程式碼塊在目標檔案中存在多個副本,即會增長目標檔案的大小;
  • 4.引數宏的執行速度會比函數快,因為不需要引數壓棧/出棧操作;
  • 5.引數宏在定義時要多加小心,多加括號;
  • 6.函數只在目標檔案中存在一處,比較節省程式空間;
  • 7.函數的呼叫會牽扯到引數的傳遞,壓棧/出棧操作,速度相對較慢;
  • 8.函數的引數存在傳值和傳地址(指標)的問題,引數宏不存在;

7.注意事項

  • 1.宏定義不會對引號內的引數進行替換;
  • 2.若要替換,可以在引數前面加上’#’轉換成“字串”,如:
#define dprint(expr) printf(#expr " = %dn", expr)

使用dprint(x/y)就被替換成:

printf("x/y" " = %gn", x/y);

printf("x/y = %gn", x/y);

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com