4

Why netinet/in.h defines constants this way?

enum
{
    IPPROTO_IP = 0,    
#define IPPROTO_IP          IPPROTO_IP
    IPPROTO_HOPOPTS = 0,   
#define IPPROTO_HOPOPTS     IPPROTO_HOPOPTS
    IPPROTO_ICMP = 1,      
#define IPPROTO_ICMP        IPPROTO_ICMP
    IPPROTO_IGMP = 2,      
    ...
};
jackhab
  • 17,128
  • 37
  • 99
  • 136
  • Don't you think the conditional's are for enabling/disabling features, e.g. if `IPPROTO_ICMP` is defined, the `IPPROTO_ICMP` enum is created and the ICMP protocol is enabled in the protocol stack. I've seen something like this in the LwIP-library. – Morten Jensen Nov 09 '15 at 12:13
  • @MortenJensen the enum should be defined in either case so that a runtime check is done rather than every application using the library doing `-DIPPROTO_xxxx=IPPROTO_xxxx` – RamblingMad Nov 09 '15 at 12:17
  • @CoffeeandCode Why would you prefer a runtime check over a compile-time check? I agree that it's in bad taste, I am only guessing at what the original author had in mind :) – Morten Jensen Nov 09 '15 at 13:35
  • @MortenJensen the compile time check is compiled into the library, the runtime check is to make sure the protocol is supported by the linked version of the library. There's gonna be a runtime check anyway, but there could be a `config.h` file or similar for a compile time check with users. – RamblingMad Nov 09 '15 at 13:37

1 Answers1

3

There's probably other code relying on #ifdef IPPROTO_IP etc.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • Although this answer is very likely highlights one side of the *truth*, however the other side still remains a question: what is the advantage of using an anonymous `enum` when the constants are also available as CPP values? Why the CPP values are not enough? – Peter Varo Nov 09 '15 at 12:17
  • 2
    As a language-level rather than preprocessor-level construct, `enum` won't get expanded/"inlined" and will remain symbolic, is more likely to appear in debuggers, guarantees that its initialization value is correctly typed and constant (`#define`s are not even guaranteed to be expressions, let alone immutable or side-effect-free), etc. – Alex Celeste Nov 13 '15 at 03:00
  • 2
    Also, part of the reason the `#ifdef`s are there is because [the standard](http://pubs.opengroup.org/onlinepubs/000095399/basedefs/netinet/in.h.html) says so (for `netinet/in.h` it is POSIX, but some macros are also defined in the ISO standards): *The header shall define the following __macros__ ....*, and the ISO C standard distinguishes *enumeration members* from *macros names*. So, defining only the enumeration members, without the macro names, would not respect the standard. – anol May 10 '17 at 11:59
  • 1
    @anol's answer seems to be correct, considering macros were added after enum values, relevant commit: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=126f53e86d8d0f1c1de802cf6ba4063c57d1a1e8 – Serdar Sanli May 13 '17 at 21:13