在 c 中为相同的标识符重用#define 是否错误?

Is it erroneous to reuse #define for the same identifier in c?

K&R 书作者说

A second #define for the same identifier is erroneous unless the second token sequence is identical to the first.

但是当我尝试时,编译器没有引发任何错误。 那么,能否请您详细说明作者想表达的意思?

如果您按照您所说的去做,它非常应该 引发诊断消息。从相关部分,C11 6.10.3 Macro replacement:

Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, ordering, spelling, and white-space separation, where all white-space separations are considered identical.

An identifier currently defined as an object-like macro shall not be redefined by another #define preprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical. Likewise, an identifier currently defined as a function-like macro shall not be redefined by another #define preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical.

例如,请参阅以下抄本:

pax:/paxhome> cat prog.c
#define X 7
#define X 99

int main(void) { return 99; }

pax:/paxhome> gcc --std=c17 prog.c -o prog
prog.c:2: warning: "X" redefined
    2 | #define X 99
      |
prog.c:1: note: this is the location of the previous definition
    1 | #define X 7
      |

请记住第一段中给出的“相同”的定义,它们不必在逐个字符的基础上完全相同。根据给出的规则,以下两个可以认为是相同的:

#define X 7 + 2
#define X \
    7 \
        + \
            2

另请记住,gcc 将此视为警告而非错误。该标准本身仅声明必须为无效程序生成 诊断 消息,但还包含以下脚注(我强调):

Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated. It may also successfully translate an invalid program.

所以 gcc 有权简单地警告你,但无论如何都要编译程序。 如果您想将警告视为错误(我倾向于将其用于我自己的代码),您始终可以将 -Werror 标志添加到编译命令(或者可能 -Wpedantic -pedantic-errors,具体取决于您的需要).