< p >
RTNLGRP_NEIGH
的值为 3。您可以使用以下程序轻松测试。
#include <stdio.h>
enum rtnetlink_groups {
RTNLGRP_NONE,
#define RTNLGRP_NONE RTNLGRP_NONE
RTNLGRP_LINK,
#define RTNLGRP_LINK RTNLGRP_LINK
RTNLGRP_NOTIFY,
#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
RTNLGRP_NEIGH,
#define RTNLGRP_NEIGH RTNLGRP_NEIGH
RTNLGRP_TC,
#define RTNLGRP_TC RTNLGRP_TC
RTNLGRP_IPV4_IFADDR,
#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
RTNLGRP_PHONET_ROUTE,
#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
int
main()
{
printf("RTNLGRP_NEIGH = %d\n", RTNLGRP_NEIGH);
}
它输出了这个:
RTNLGRP_NEIGH = 3
由于每个宏都被定义为其自己的名称,因此在
main
中的
RTNLGRP_NEIGH
将被替换为
RTNLGRP_NEIGH
。但由于该扩展不是递归的,它将在此处停止,并且程序使用第四个枚举常量
RTNLGRP_NEIGH
,其值为3。
如果您不确定预处理器的作用,可以始终使用
-E
开关编译并查看预处理输出。使用
gcc -E
编译上面的示例会产生(未显示840行
#include
的标准库头文件)。
# 4 "main.c"
enum rtnetlink_groups {
RTNLGRP_NONE,
RTNLGRP_LINK,
RTNLGRP_NOTIFY,
RTNLGRP_NEIGH,
RTNLGRP_TC,
RTNLGRP_IPV4_IFADDR,
RTNLGRP_PHONET_ROUTE,
__RTNLGRP_MAX
};
int
main()
{
printf("RTNLGRP_NEIGH = %d\n", RTNLGRP_NEIGH);
}
希望这篇翻译能让您更易理解。
在枚举定义中混合使用的 #define 对枚举定义没有影响。无论 #define 放在何处,都不会对枚举定义造成影响。它们可以(并且应该)放置在定义之前或之后。
enum rtnetlink_groups {
RTNLGRP_NONE,
RTNLGRP_LINK,
RTNLGRP_NOTIFY,
RTNLGRP_NEIGH,
RTNLGRP_TC,
RTNLGRP_IPV4_IFADDR,
RTNLGRP_PHONET_ROUTE,
__RTNLGRP_MAX
};
#define RTNLGRP_NONE RTNLGRP_NONE
#define RTNLGRP_LINK RTNLGRP_LINK
#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
#define RTNLGRP_NEIGH RTNLGRP_NEIGH
#define RTNLGRP_TC RTNLGRP_TC
#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
他们写这个奇怪的代码的原因可能是想使用重构旧代码。
/* ... */
使用
enum
替代宏定义。但是,由于现有代码可能依赖于标识符是宏定义(例如测试
#ifdef RTNLGRP_NEIGH
),因此他们希望提供具有相同值的宏定义。请注意,然而这种方法是有缺陷的,因为预处理器不知道常量的值,所以你不能像这样做:
#if RTNLGRP_NEIGH >= 3
,如果
RTNLGRP_NEIGH
被直接定义为
3
的话是可以的。因此,实质上,他们的方法结合了使用宏定义(命名空间污染)和使用
enum
(无法在预处理时使用)的缺点。
我曾经看到过一种更有用的模式,即将常量定义为实际的整数值。
enum rtnetlink_groups {
RTNLGRP_NONE
#define RTNLGRP_NONE 0
= RTNLGRP_NONE,
RTNLGRP_LINK
#define RTNLGRP_LINK 1
= RTNLGRP_LINK,
RTNLGRP_NOTIFY
#define RTNLGRP_NOTIFY 2
= RTNLGRP_NOTIFY,
RTNLGRP_NEIGH
#define RTNLGRP_NEIGH 3
= RTNLGRP_NEIGH,
RTNLGRP_TC
#define RTNLGRP_TC 4
= RTNLGRP_TC,
RTNLGRP_IPV4_IFADDR
#define RTNLGRP_IPV4_IFADDR 5
= RTNLGRP_IPV4_IFADDR,
};
这将被预处理为以下内容。
enum rtnetlink_groups {
RTNLGRP_NONE
= 0,
RTNLGRP_LINK
= 1,
RTNLGRP_NOTIFY
= 2,
RTNLGRP_NEIGH
= 3,
RTNLGRP_TC
= 4,
RTNLGRP_IPV4_IFADDR
= 5,
};
请注意,在这里,将
#define
混合到
enum
定义中非常关键,否则我们会得到无效的代码,例如
3 = 3
,而不是所需的
RTNLGRP_NEIGH = 3
。
另外,请不要使用
__RTNLGRP_MAX
作为标识符。包含两个相邻下划线或以下划线后跟大写字母的名称已被C标准保留。在您自己的代码中使用它们会导致未定义的行为。