在结构中定义宏的逻辑是什么?

正如标题中所显示的,我正在质疑在结构中定义宏的原因。 我经常在网络编程中看到这种方法,例如以下片段:

struct sniff_tcp { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ u_char th_offx2; /* data offset, rsvd */ #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4) u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; 

此示例来自tcpdump网站中的sniffex.c代码。

这是为了增强可读性和使代码更清晰。

我认为,这不是“最佳实践”,应该在结构附近保留定义(对于值),而不是在结构内部。

(更好的是enum和typedef常量,因此如果没有正确输入,编译器可能会发出警告)。

TH_OFF()宏是另一种情况,它“隐藏”另一个元素,所以也许它可以放在这个位置(带有适当的注释)

好吧,定义的常量与其中一个字段的可能值相关。

因此,作者决定改进代码局部性,并使API用户避免在圈内运行。 似乎合乎逻辑。

否则,预处理器完全独立于代码。 您甚至可以在表达式中放置一个定义。

我们不得不怀疑它试图向我们传达这些宏只与这个结构中的数据一起使用,但这是一种很糟糕且复杂的方式来表示它。

在C ++中,最好使用嵌套的枚举和内联函数来实现这一点,但由于代码是C,宏可能是最好的选择。

在我看来,它降低了可读性,我更愿意看到结构外部的宏,注释表明它们应该在何处以及如何使用。 这样就无法猜测宏究竟是为了什么而且结构定义没有任何缺陷。

一种典型用法如下所示

包括

假设您的第一个版本的foo有点如下所示。

 struct foo1 { int x;`enter code here` ... }; 

明天你会尝试通过以下方式增强结构

 struct foo2 { union { int x; int y; } u; #define x ux #define y uy }; 

上面做的声明不会破坏你使用foo_var.x的地方的编译,因为结构的新定义foo_var.x仍然有效,只不过是foo_var.ux

例如:用法:

 struct foo { union { int x; int y; } u; #define x ux #define y uy }; int main() { struct foo f; fx = 1; fy = 2; } 

作者的意图似乎是属于一起的东西应该放在一起。 因此,标志宏应位于标志下方。 使用相同的逻辑,宏定义与结构声明无关,因此宏属于那里。 将它们放在结构的上方或下方没有任何问题。

我想知道如果该标志是一个带有32个标志宏的u_long和一些更多的额外默认组合宏,那么作者是否会保持一致并做同样的事情?