簡體   English   中英

C中的宏觀和功能沖突

[英]macro and function conflict in C

當C中的宏和函數沖突出現時會引發什么錯誤? 是宏處理器錯誤還是由於某些語言違規而發生此錯誤?

例如,在此代碼中:

#include <stdio.h>
#define MAX(i, j) (i>j)? i : j

int MAX(int i, int j){
  return (i>j) ? i : j;
}

int main(){
  int max = MAX(5, 7);
  printf("%d",max);
  return 0;
}

該程序拋出編譯時錯誤。 但我不明白它是否是某種語言違規或宏擴展錯誤或其他原因。

在預處理階段,代碼轉換為:

int (int i>int j)? int i : int j{
  return (i>j) ? i : j;
}

int main(){
  int max = (5>7)? 5 : 7;
  printf("%d",max);
  return 0;
}

...正如任何人都知道的那樣,是非法的C代碼。

(使用gcc您可以使用-E選項查看文件的預處理版本。)

其他人指出了問題,但沒有給出任何解決方案。 最好的方法是使用MAX作為內聯函數。 如果宏位於標題中,請將內聯函數定義放在標題中。 如果您仍希望使用宏(或使用不支持內聯函數的舊C編譯器),則可以通過以下方式定義函數:

int (MAX)(int i, int j){
    return (i>j) ? i : j;
}

這將防止令人不安的宏擴展並提供MAX作為外部功能。 例如,這將使您能夠將其地址分配給變量。

extern int (MAX)(int, int);
...
int (*max_func_ptr)(int, int);
...
max_func_ptr = MAX;

您將收到編譯器錯誤,因為在嘗試編譯之前將擴展宏。

這是一個非常討厭的問題,並且沒有真正的解決方案。 因此,您應該盡可能避免定義無范圍的,類似函數的宏,尤其是在廣泛包含的標頭中。 像所有東西一樣,它們都有它們的位置,但你需要注意不要過度使用它們。

沒有任何錯誤特別發生,以確定存在沖突。 會發生什么是宏處理首先發生,所以在某種意義上宏定義不尊重名稱空間 - 這是宏被認為是壞形式的主要原因之一,應該避免,除非作為最后的手段。 請參閱此問題,以獲取一個例子,其中某人完全有效地使用名稱BitTest作為模板被搞砸了,因為其他人決定使用該名稱創建一個宏來“別名”另一個名稱: Win32:BitTest,BitTestAndComplement,.. 。< - 如何禁用這個垃圾?

因此,在您的示例中,正如其他答案所提到的,一旦預處理步驟發生,您將最終得到類似下面的代碼段傳遞給C編譯器代替您的函數定義:

int (int i>int j)? int i : int j{
  return (i>j) ? i : j;
}

這不是有效的C,因此您可能會遇到編譯器錯誤(來自GCC 3.4.5):

error: syntax error before "int"

或(來自MSVC 9):

error C2059: syntax error : 'type'

這真的沒什么幫助,因為當你看到錯誤在你的編輯器中引用的那一行時,它仍然看起來像:

int MAX(int i, int j){

看起來有效。

有幾種技術可用於幫助避免此問題:

  • 對宏名稱和宏名稱使用全部大寫; 這是一個大致遵循的約定,以使宏命名空間與用於其他事物的名稱分開

  • 將parens放在你不希望擴展為宏的名稱周圍(這僅適用於'類似函數'的宏)。 如果您的示例編寫如下:

     int (MAX)(int i, int j){ return (i>j) ? i : j; } 

    它不會導致宏觀擴張。 但是,我不認為人們經常這樣做。 我使用的一組實用程序例程使用這種技術來防止宏命名沖突,我經常會問到為什么所有的函數名都在parens中。 此外,一些編輯也對這些文件的功能導航感到困惑。

  • 避免使用宏; 正如我所提到的,這是宏被認為是壞形式的一個原因。 還有其他原因包括如果您沒有在宏參數周​​圍正確使用parens或者通過評估具有多次副作用的宏參數,它們很容易導致擴展形式產生錯誤或意外的表達式。

    如果可以,請使用內聯函數或函數模板。

由於預處理器宏僅用於處理純文本,因此這些沖突總是會導致編譯時錯誤。

預處理首先發生,因此第4行將變為:

int (int i>int j)? int i : int j

這是無效的C.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM