C语言的预编译是先于enum,什么意思呢,看代码:

#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>

enum
{
    ENUM_ABC,
    ENUM_DEF,
};

#define DEF ENUM_DEF    

int main(int argc, char **argv)
{
#if DEF == ENUM_ABC
    printf("ENUM_ABC\r\n");
#elif DEF == ENUM_DEF
    printf("ENUM_DEF\r\n");
#endif

    return 0;
}

一开始觉得运行结果应该是“ENUM_DEF”,但是实际上是:

【C语言】预编译先于enum_C/C

这种低级问题我还想了很久才想起来,C语言在预编译的时候,预编译器只是展开#include、#define等命令,处理条件编译#if、#else等命令,删除注释,添加行号和文件标识等操作,所以这个时候枚举类型是“未生效”的,枚举类型数据的“展开”是在编译阶段由编译器进行的,因此这里 “#if DEF == ENUM_ABC” 在预编译的时候就会有问题,按道理预编译器会报 ENUM_ABC 和 ENUM_DEF 未定义的警告或者错误(根据gcc的-Wundef -Eundef标志),如果没有设置成报错,那么编译器会把未定义的这个宏设置成0(evaluates to 0),因此这句话 “#if DEF == ENUM_ABC” 的展开流程为:

DEF ==>> ENUM_DEF

ENUM_DEF ==>> 0

ENUM_ABC ==>> 0

那么 #if DEF == ENUM_ABC 就是 #if 0 == 0,因此永远在第一条就成立,所以输出的就是 “ENUM_ABC”。

想要控制编译流程的话,还是要用 #define 的方式来控制:

#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>

#define ENUM_ABC 0
#define ENUM_DEF 1

#define DEF ENUM_DEF    

int main(int argc, char **argv)
{
#if DEF == ENUM_ABC
    printf("ENUM_ABC\r\n");
#elif DEF == ENUM_DEF
    printf("ENUM_DEF\r\n");
#endif

    return 0;
}

这样输出就正确了。