What is the logic for defining macros within a structure?

As you see in the title, I wonder about the reason for defining macros within a structure. I often see this approach in network programming, for example, the following snippet:

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 */ }; 

This example is from sniffex.c on the tcpdump website.

This improves readability and makes code easier to understand.

+4
source share
5 answers

I think this is not "best practice", you need to keep the definitions (for values) next to the structure, but not inside the structure.

(It would be even better to list typedef constants as well, so the compiler could warn if it didn't type correctly).

The macro TH_OFF () is another case when it β€œhides” another element, so perhaps it can be placed at this position (with the corresponding comment)

+1
source

Well, certain constants were relevant to the possible values ​​of one of the fields.

So, the author decided to improve the locality of the code and force the users of the API to avoid using in circles. Is logical.

Otherwise, the preprocessor is completely code independent. You can even define a definition inside an expression.

+6
source

We should suspect that he is trying to convey to us that macros should only be used in conjunction with the data in this structure, but this is a bad and confusing way to represent it.

In C ++, it might be preferable to use a nested enumeration and a built-in function to accomplish this, but since C code, a macro is probably the best alternative.

In my opinion, this reduces readability, and I would rather see macros outside the structure with comments indicating where and how they should be used. Thus, there is no speculation as to what exactly macros are intended for, and the definition of structure remains free from cracks.

+3
source

one typical use as shown below

turn on

Suppose your first version of foo is shown somewhat below.

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

And tomorrow you will try to improve the structure of foo as follows.

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

The declaration made above will not break compilation in those places where you have used foo_var.x, since with the new definition struct foo_var.x is still valid and nothing but foo_var.ux

for example use:

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

The purpose of the author is that things that belong to each other should be located together. Therefore, flag macros must be flagged. With the same logic, the definition of a macro has nothing to do with the declaration of a structure, so macros do not . There is nothing wrong with placing them above or below the structure.

I wonder if the author would be consistent and do the same if the flag were u_long with 32 flag macros and a few extra default macros?

+1
source

Source: https://habr.com/ru/post/1312943/


All Articles