如果我在没有undef指令的情况下在C中重新定义宏会怎样?

时间:2019-03-01 11:21:50

标签: c macros c-preprocessor

我想知道我的编译器针对“宏MACRO_NAME重新定义”抛出的警告的严重性。它在没有undef指令的头文件中重新定义,如下所示:

#define MACRO_NAME 3.14
/*other macro definition*/
#define MACRO_NAME 8192

在整个程序中,MACRO_NAME取什么值?它取决于编译器吗?这里是#undef必需的吗?

4 个答案:

答案 0 :(得分:1)

如果编译,则用第二个宏的值覆盖第一个宏。

#include <stdio.h>

#define MACRO_NAME 3.14
/*other macro definition*/
#define MACRO_NAME 8192

int main()
{
    printf("%d", MACRO_NAME);

    return 0;
}

输出:8192

通常会收到此警告,并且应始终使用#undef,因为根据C89标准,这样的重定义是无效的:

  

5:0:警告:“ MACRO_NAME”已重新定义

     

3:0:注意:这是先前定义的位置

由cpp.sh,onlinegdb.com和tutorialspoint.com验证。

答案 1 :(得分:1)

第二个宏int a; #define VAL 100 a=VAL; // a is 100 here #define VAL 200 a=VAL; // a is 200 here 被考虑在内。无论如何,这都是不好的做法,因为当新开发人员读取您编写的整个代码时,这可能会引起巨大的混乱。

通常,在不同的头文件中用不同的值定义的同一宏可能会发生,这时取决于这两个头文件的包含顺序。看到这种情况,这对您来说可能很容易,但是当新开发人员接管您的代码时,这会造成极大的混乱。

通常,将所有警告视为错误。然后,您不必担心宏将具有什么值。(摘自上面的评论)

我不建议您在没有undef的情况下重新定义宏

通常,您会收到此警告,并且应始终使用#undef,因为根据C89标准,这种重新定义无效:

一个很好的例子已经提出:

words

您可以看到问题所在:)

答案 2 :(得分:1)

来自C标准#6.10.3p2 [强调我的]

  

2当前定义为类对象宏的标识符不应由另一个#define预处理指令重新定义,除非第二个定义是类对象宏定义和两个替换列表完全相同。同样,当前定义为类函数宏的标识符不应由另一个#define预处理指令重新定义,除非第二个定义是具有相同编号和参数拼写且两个替换列表相同的类函数宏定义。

因此,根据标准,这无效,因为替换项(3.148192)不相同:

#define MACRO_NAME 3.14
/*other macro definition*/
#define MACRO_NAME 8192

您可以使用#undef使此代码有效,如下所示:

#define MACRO_NAME 3.14
 // the part of code using MACRO_NAME before #undef will expanded to 3.14
#undef MACRO_NAME

/*other macro definition*/
#define MACRO_NAME 8192
 // after this the code using MACRO_NAME expanded to 8192

来自C标准#6.10.3.5p1(宏定义的范围) [已添加重点]

  

1 宏定义将持续(独立于块结构),直到遇到相应的#undef指令为止;或者(如果未遇到)直到预处理转换单元的末尾。宏定义没有任何意义。在翻译阶段4之后。


其他:

从C Standard#6.10.3.5p8开始,宏重新定义规则演示:

  

8示例6为了演示重新定义规则,以下顺序有效。

     #define      OBJ_LIKE      (1-1)
     #define      OBJ_LIKE      /* white space */ (1-1) /* other */
     #define      FUNC_LIKE(a)   ( a )
     #define      FUNC_LIKE( a )( /* note the white space */ \
                                   a /* other stuff on this line
                                       */ )
     

但是以下重新定义无效:

     #define      OBJ_LIKE    (0)     // different token sequence
     #define      OBJ_LIKE    (1 - 1) // different white space
     #define      FUNC_LIKE(b) ( a ) // different parameter usage
     #define      FUNC_LIKE(b) ( b ) // different parameter spelling

答案 3 :(得分:1)

您正在做的事情无效:

C11标准规定:

  

6.10.3宏替换
  约束
  ...
  2当前定义为类对象宏的标识符不能由另一个#define预处理指令重新定义,除非第二个定义是类对象宏定义和两个替换列表完全相同

     

当且仅当两个中的预处理令牌具有相同的数字,顺序,拼写和空格分隔(其中所有空格分隔均视为相同)时,两个替换列表相同。 / p>

对于

#define MACRO_NAME 3.14

#define MACRO_NAME 8192

替换列表不同