╰─ make Consolidate compiler generated dependencies of target app [ 50%] Building CXX object CMakeFiles/app.dir/main.cpp.o /home/calm/calm/tmp/test/cpp/main.cpp:3:14: error: expected identifier before numeric constant 3 | #define NAME 5 | ^ /home/calm/calm/tmp/test/cpp/main.cpp:7:5: note: in expansion of macro ‘NAME’ 7 | NAME = 0 | ^~~~ /home/calm/calm/tmp/test/cpp/main.cpp:3:14: error: expected ‘}’ before numeric constant 3 | #define NAME 5 | ^ /home/calm/calm/tmp/test/cpp/main.cpp:7:5: note: in expansion of macro ‘NAME’ 7 | NAME = 0 | ^~~~ /home/calm/calm/tmp/test/cpp/main.cpp:6:1: note: to match this ‘{’ 6 | { | ^ /home/calm/calm/tmp/test/cpp/main.cpp:3:14: error: expected unqualified-id before numeric constant 3 | #define NAME 5 | ^ /home/calm/calm/tmp/test/cpp/main.cpp:7:5: note: in expansion of macro ‘NAME’ 7 | NAME = 0 | ^~~~ /home/calm/calm/tmp/test/cpp/main.cpp:8:1: error: expected declaration before ‘}’ token 8 | } tenuTest; | ^ /home/calm/calm/tmp/test/cpp/main.cpp:8:3: error: ‘tenuTest’ does not name a type 8 | } tenuTest; | ^~~~~~~~ make[2]: *** [CMakeFiles/app.dir/build.make:76: CMakeFiles/app.dir/main.cpp.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/app.dir/all] Error 2 make: *** [Makefile:91: all] Error 2
要怎么解释这个现象?宏是在预编译阶段处理并完成替换的,而枚举是在编译阶段处理,在编译阶段将枚举转换成相应的值。从上往下如果见定义的是枚举,预编译阶段并不会处理枚举,接着往下到 NAME 的宏定义开始,之后遇到的 NAME 字符串都被替换为整数 5 ,这是程序运行输出值为5的原因,再到编译阶段开始处理枚举定义,但此时预编译阶段已经结束,NAME 已经被宏替换为 5 ,编译器会发现枚举 NAME 并为被使用,但这不构成错误,编译器不会报出任何错误和警告。第二段程序交换了枚举和宏的定义顺序为什么又能报错?先定义了 NAME 宏,会将枚举定义中 NAME = 0 的 NAME 替换为5,到编译阶段发现枚举中 5 = 5 当然就报错了。
2 危害
这个错误可能导致使用的值并不是开发者所预期的,比如开发者与其输出的是枚举 NAME 的值,即0,但程序实际值是5,从而可能引发各种非预期的程序Bug。特别在大型复杂的项目中,枚举和宏可能定义在不同的模块中,编译器也不会发现错误,将会是一个很隐蔽的Bug,比如以下代码。