编译器如何处理枚举中的符号常量?

How compiler handles symbolic constants in enumerations?

如果我们谈论宏而不是编译器在预处理阶段处理它们,那么枚举器呢?编译器如何看待它们。例如看下面的代码:

#include <stdio.h> 
enum day {sunday = 1, monday, tuesday = 5, 
        wednesday, thursday = 10, friday, saturday}; 

int main() 
{ 
    printf("%d %d %d %d %d %d %d", sunday, monday, tuesday, 
            wednesday, thursday, friday, saturday); 
    return 0; 
} 

在这个特定示例中,我什至没有为枚举数据类型创建任何变量。我只是在 printf() 语句中使用了 enumeration-constants。枚举器在内部的工作方式类似于宏吗?在预处理过程中,所有这些符号常量都会被整数常量替换吗?编译器究竟如何处理它们?

不,它们不像宏那样工作,它们更像是常量变量。

所以你的代码大致等同于:

#include <stdio.h> 

const int sunday = 1, monday = 2, tuesday = 5, 
        wednesday = 6, thursday = 10, friday = 11, saturday = 12; 

int main() 
{ 
    printf("%d %d %d %d %d %d %d", sunday, monday, tuesday, 
            wednesday, thursday, friday, saturday); 
    return 0; 
}

在这里查看:https://www.godbolt.org/z/cErv5W

不,枚举在内部不像宏那样工作,枚举是一种在编译期间评估的数据类型,而预处理器将宏复制为文本。

来自 gcc gnu 文档: 宏是已被赋予名称的代码片段。每当使用该名称时,它都会被宏的内容替换。有两种宏。它们的主要区别在于使用时的外观。 Object-like 宏在使用时类似于数据对象,function-like 宏类似于函数调用。

枚举是C语言中用户定义的数据类型。它用于为整数常量分配名称,使程序易于阅读和维护。关键字“enum”用于声明枚举。

Do enumerators work similar to macros internally ?

有些是,有些不是。

Will all these symbolic constants be replaced by there integer constants during preprocessing ?

没有。除了预处理指令、defined 运算符和定义的宏名称之外,预处理器不知道一个标识符与另一个标识符的区别。你可以试试这个:

#include <stdio.h>

#define MACRO_TRUE 1
enum bool_enum { ENUM_FALSE = 0, ENUM_TRUE = 1 };

int main(void) {
#if MACRO_TRUE
    puts("Macro identifiers are known to the preprocessor.");
#else
    puts("Macro identifiers are not known to the preprocessor.");
#endif
#if ENUM_TRUE
    puts("Enum constants are known to the preprocessor.");
#else
    puts("Enum constants are not known to the preprocessor.");
#endif
}

输出应该是

Macro identifiers are known to the preprocessor.
Enum constants are not known to the preprocessor.

How exactly compiler handles them ?

In-scope 枚举常量类似于其他整数常量,例如 42,除了上面的警告,预处理器不会这样解释它们。例如,它们可用于整数常量表达式,用于各种目的,例如 switch 语句中的 case 标签。该标准未指定详细信息,但大多数编译器将它们与宏类似地对待,因为在可执行文件中没有为它们保留存储空间——源代码被视为枚举常量在它们出现在表达式中的任何地方都被它们相应的整数值替换,之后 pre-processing。当然它们不标识对象,因为它们不是 & 运算符可接受的操作数。

这是为了区别于const限定变量的行为。这些标识实际对象,而不仅仅是常量。它们可能不会在常量表达式中使用,并且它们确实有与之关联的存储(至少在抽象机中),因此它们的地址可以通过 & 运算符获得。