我在浏览一些route netlink源代码。
我想弄清楚rtnlgrp廑u neigh的价值是什么
来源:http://lxr.free-electrons.com/source/include/linux/rtnetlink.h?v=2.6.35#L550
541 /* RTnetlink multicast groups */
542 enum rtnetlink_groups {
543 RTNLGRP_NONE,
544 #define RTNLGRP_NONE RTNLGRP_NONE
545 RTNLGRP_LINK,
546 #define RTNLGRP_LINK RTNLGRP_LINK
547 RTNLGRP_NOTIFY,
548 #define RTNLGRP_NOTIFY RTNLGRP_NOTIFY
549 RTNLGRP_NEIGH,
550 #define RTNLGRP_NEIGH RTNLGRP_NEIGH
551 RTNLGRP_TC,
552 #define RTNLGRP_TC RTNLGRP_TC
553 RTNLGRP_IPV4_IFADDR,
554 #define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR
... ...
... ...
#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
585 RTNLGRP_PHONET_ROUTE,
586 #define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
587 __RTNLGRP_MAX
588 };
589 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
define doing的枚举是什么。
RTNLGRP的价值是什么?
6 OR 3
谢谢
最佳答案
RTNLGRP_NEIGH
的值为3。您可以使用下面的程序轻松地对此进行测试。
#include <stdio.h>
/* RTnetlink multicast groups */
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
由于每个宏的名称都是
#define
d,因此RTNLGRP_NEIGH
中的main
将替换为RTNLGRP_NEIGH
。但由于扩展不是递归的,所以它将在此时停止,程序使用enum
常量RTNLGRP_NEIGH
,这是第四个常量,因此具有值3。如果您不确定预处理器做什么,您可以始终使用
-E
开关编译并查看预处理的输出。用gcc -E
编译上面的示例给出(没有显示840行#include
d标准库头)# 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
定义中的enum
s对enum
定义没有影响。#define
s位于何处并不重要。它们可以(也可能应该)放在定义之前或之后。/* RTnetlink multicast groups */
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)
他们写这些怪代码的原因可能是他们想用
#define RTNLGRP_NONE 0
#define RTNLGRP_LINK 1
#define RTNLGRP_NOTIFY 2
#define RTNLGRP_NEIGH 3
#define RTNLGRP_TC 4
#define RTNLGRP_IPV4_IFADDR 5
/* ... */
改为使用
enum
。但是,因为现有代码可能依赖于标识符是宏(例如测试#ifdef RTNLGRP_NEIGH
)的事实,所以它们希望提供具有相同值的宏。注意,这种方法是有缺陷的,但是,因为预处理器不知道常量的值,所以您不能做像#if RTNLGRP_NEIGH >= 3
这样的事情,如果RTNLGRP_NEIGH
已经#define
d到3
字面上的话。因此,本质上,他们的方法结合了使用宏(名称空间污染)和使用enum
s(在预处理时不可用)的缺点。我以前见过的一个更有用的模式是将常量转换成实际整数。
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
s必须混合到#define
定义中,否则我们将得到诸如enum
之类的无效代码,而不是所需的3 = 3,
。哦,请不要使用
RTNLGRP_NEIGH = 3
作为标识符。包含两个相邻下划线或以下划线开头,后跟大写字母的名称由C标准保留。在自己的代码中使用它们会导致未定义的行为。关于c - 令人困惑的MACRO和枚举定义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45778074/