Has*_*ell 3 c enums c-preprocessor
我正在浏览一些Route netlink源代码.
我想弄清楚RTNLGRP_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)
Run Code Online (Sandbox Code Playgroud)
#define做的这个枚举是什么.RTNLGRP_NEIGH的价值是多少?6 OR 3
谢谢
值为RTNLGRP_NEIGH3.您可以使用以下程序轻松测试.
#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);
}
Run Code Online (Sandbox Code Playgroud)
它输出这个:
RTNLGRP_NEIGH = 3
Run Code Online (Sandbox Code Playgroud)
由于每个宏都是#define自己的名称,因此RTNLGRP_NEIGHin main将替换为RTNLGRP_NEIGH.但由于扩展不是递归的,它将在此时停止,程序使用第四个enum常量RTNLGRP_NEIGH,因此值为3.
如果您不确定预处理器的作用,您始终可以使用-E开关进行编译并查看预处理的输出.编译上面的例子gcc -E给出(没有显示d40 #include标准库头的840行)
# 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);
}
Run Code Online (Sandbox Code Playgroud)
希望更容易混淆.
#define混入enum定义的s对定义没有影响enum.#defines位于何处无关紧要.他们可以(也可能应该)在定义之前或之后放置.
/* 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)
Run Code Online (Sandbox Code Playgroud)
他们编写这个weired代码的原因可能是他们想要使用重构旧代码
#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
/* ... */
Run Code Online (Sandbox Code Playgroud)
用一个enum代替.但由于现有代码可能依赖于标识符是宏(例如测试#ifdef RTNLGRP_NEIGH)这一事实,因此他们希望为宏提供相同的值.注意,这种方法是有缺陷的,但是,因为预处理器将不知道常数的值,所以你不能做这样的事情#if RTNLGRP_NEIGH >= 3,你可以,也RTNLGRP_NEIGH被#define剐到3字面上.因此,从本质上讲,他们的方法结合了使用宏(名称空间污染)和使用宏(enum在预处理时不可用)的缺点.
我之前看到的一个可能更有用的模式是#define常量到实际整数.
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,
/* ... */
};
Run Code Online (Sandbox Code Playgroud)
将被预处理到以下.
enum rtnetlink_groups {
RTNLGRP_NONE
= 0,
RTNLGRP_LINK
= 1,
RTNLGRP_NOTIFY
= 2,
RTNLGRP_NEIGH
= 3,
RTNLGRP_TC
= 4,
RTNLGRP_IPV4_IFADDR
= 5,
};
Run Code Online (Sandbox Code Playgroud)
请注意,在这里,将#defines混合到enum定义中是至关重要的,否则我们会得到无效的代码,3 = 3,而不是所需的代码RTNLGRP_NEIGH = 3.
哦,请不要__RTNLGRP_MAX用作标识符.包含两个相邻下划线或以下划线开头后跟大写字母的名称由C标准保留.在您自己的代码中使用它们会导致未定义的行为.
| 归档时间: |
|
| 查看次数: |
491 次 |
| 最近记录: |