簡體   English   中英

C中級聯宏的規則

[英]Rules for cascading macros in C

我無法找到處理下面案例的C預處理器的規則。 如果你假設一個直接替換,這種情況甚至不應該編譯,因為a=--1 但如果你假設用括號替換,那么a=-(-1) = 1

#include <stdio.h>
#define  ALPHA -1
#define  BETA -ALPHA
int main(void) {
    int a = BETA;
    int b = -ALPHA; // this compiles too, why? b = --1
    printf("%d\n",a); // 1
    return 0;
}

預處理是編譯之前的階段,它生成一個預處理轉換單元,它將作為編譯器的輸入。

其過程中的一些步驟是( 來自 C99 5.1.1.2 ):

  1. 源文件被分解預處理令牌 (......)

  2. 執行預處理指令, 擴展宏調用 ,(...)

正如您所見,Tokenization 宏調用之前,因此-ALPHA將被視為2個單獨的預處理令牌(* ie -ALPHA 1 ),而不是您認為的2個預處理令牌--1--1

在第7條之后:

  1. 分隔標記 的空白字符不再重要 每個預處理令牌都轉換為令牌。

因此編譯器將獲得令牌並忽略空格。

如果使用gcc -E生成預處理文件gcc -E空格沒有任何意義,而您所看到的僅用於格式化為用戶,並且無法反映CPP的實際內部行為。

來自GCC CPP 5.4.0 1.3

令牌不必用空格分隔 ,但通常需要避免歧義 (...)

一旦輸入文件被分解為令牌, 令牌邊界永遠不會改變 ,除非使用'##'預處理操作符將令牌粘貼在一起

編譯器不會重新標記預處理器的輸出 每個預處理令牌都成為一個編譯器令牌。

總結:

如果你寫-ALPHA =>令牌是:

  • -標點符號 - 二進制減號

  • -標點符號 - 二進制減號

  • 1常數 - 整數常量

如果你寫--1 =>令牌是:

  • -- punctuator - 遞減運算符

  • 1常數 - 整數常量

遞減運算符不應該與常量一起使用,這就是編譯期間在這種情況下出錯的原因。


1: ALPHA標識符將兩個預處理標記替換 (在第4階段) -並且在宏定義中標識 1

這是您的程序在預處理完成后的樣子。

int main(void) {
    int a = - -1;
    int b = - -1;
    printf("%d\n",a);
    return 0;
}

您可以使用-E選項和gcc一起查看此輸出。

絕對不是--1 注意額外的空間。

首先要了解C預處理器不是編譯過程的一部分。 它只是替換過程,它告訴編譯器在實際編譯之前進行必要的預處理。

要了解很多,你必須閱讀宏觀陷阱

暫無
暫無

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

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