Macros 为什么struct的某些变量需要预处理器来运行?
头文件中语言的数据类型声明的结构变量。通常使用数据类型来声明变量,但其他数据类型传递给预处理器。什么时候我们应该使用数据类型发送给预处理器来声明变量?为什么数据类型和变量发送到处理器Macros 为什么struct的某些变量需要预处理器来运行?,macros,struct,preprocessor,c-preprocessor,Macros,Struct,Preprocessor,C Preprocessor,头文件中语言的数据类型声明的结构变量。通常使用数据类型来声明变量,但其他数据类型传递给预处理器。什么时候我们应该使用数据类型发送给预处理器来声明变量?为什么数据类型和变量发送到处理器 #define DECLARE_REFERENCE(type, name) \ union { type name; int64_t name##_; } typedef struct _STRING { int32_t flags; int32_t length; DECLARE_REFE
#define DECLARE_REFERENCE(type, name) \
union { type name; int64_t name##_; }
typedef struct _STRING
{
int32_t flags;
int32_t length;
DECLARE_REFERENCE(char*, identifier);
DECLARE_REFERENCE(uint8_t*, string);
DECLARE_REFERENCE(uint8_t*, mask);
DECLARE_REFERENCE(MATCH*, matches_list_head);
DECLARE_REFERENCE(MATCH*, matches_list_tail);
REGEXP re;
} STRING;
为什么这段代码对声明执行此操作?因为正如DECLARE\u REFERENCE
的主体所示,当类型和名称被传递给这个宏时,它所做的不仅仅是声明——它还从名称中构建了其他东西,用于其他未知的目的。如果你只想声明一个变量,你就不会这么做——它做的事情不同于简单地声明一个变量
它实际上是做什么的?宏声明的联合为以不同类型访问同一空间提供了第二个名称。在这种情况下,可以获取引用本身,也可以获取其位模式的未转换整数表示。无论如何,假设int64\t
与目标上的指针大小相同
为此使用宏可能有以下几种用途,我可以立即想到:
所以这里的全部课程是确定人们不是用简单的C语言编写代码,而是为他们的特定应用程序编写代码的地方,并将这两者分开,不要把某个特定程序中的怪癖作为整个语言的指导方针。有时需要有一些声明,保证它们之间有某种关系。一些简单类型的关系,例如需要连续编号的常量,可以使用
enum
声明来处理,但有些应用程序需要更复杂的关系,编译器无法直接处理这些关系。例如,您可能希望拥有一组枚举值和一组字符串文本,并确保它们彼此保持同步。如果有人宣称:
#define GENERATE_STATE_ENUM_LIST \
ENUM_LIST_ITEM(STATE_DEFAULT, "Default") \
ENUM_LIST_ITEM(STATE_INIT, "Initializing") \
ENUM_LIST_ITEM(STATE_READY, "Ready") \
ENUM_LIST_ITEM(STATE_SLEEPING, "Sleeping") \
ENUM_LIST_ITEM(STATE_REQ_SYNC, "Starting synchronization") \
// This line should be left blank except for this comment
然后,代码可以使用GENERATE_STATE_ENUM_LIST
宏来声明ENUM
类型和字符串数组,并确保即使从列表中添加或删除了项,每个字符串也将与其正确的枚举值相匹配。相反,如果数组和枚举声明是分开的,则向其中一个声明添加新状态(而不是另一个声明)可能会导致值“不同步”
我不确定宏在特定情况下的用途,但这种模式有时是合理的。最大的“问题”是(ab)是否最好使用C预处理器,以便用有效但难看的C代码来表示这种关系,或者是否最好使用其他工具获取状态列表,并从中生成适当的C代码