14

One header socket.h on my Linux system looks like the following.

/* Bits in the FLAGS argument to `send', `recv', et al.  */
enum
  {
    MSG_OOB             = 0x01, /* Process out-of-band data.  */
#define MSG_OOB         MSG_OOB
    MSG_PEEK            = 0x02, /* Peek at incoming messages.  */
#define MSG_PEEK        MSG_PEEK
    MSG_DONTROUTE       = 0x04, /* Don't use local routing.  */
#define MSG_DONTROUTE   MSG_DONTROUTE
...

Defining an enum is sort of an idiom for creating type-safe-ish constants in C that the language actually treats as compile-time constants.

My question is : what purpose does the definition of macros MSG_OOB, MSG_PEEK, … that expand to themselves serve?

Community
  • 1
  • 1
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • I have never seen it but I guess it overwrites any possible alternative definition so you are sure it is only the enum. – Floris Feb 18 '14 at 13:34
  • `MSG_OOB` expand to `MSG_OOB`. – BLUEPIXY Feb 18 '14 at 13:35
  • @GIJoe You may be on to something here. They won't expand to a value the pre-processor can use, but `#ifdef MSG_PEEK` will work as expected if someone needs to write it. – Pascal Cuoq Feb 18 '14 at 13:40

2 Answers2

9

The purpose of these defines is that the application can do something like

#ifdef MSG_OOB
  some code here
#endif

expansion of macros is not recursive so the evaluation of macro MSG_OOB results in the enum constant MSG_OOB of the same name.

To also have the constants declared as enum helps for example when you are debugging.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Actually, this answer is wrong. See @Sneftel's answer. – Engineer2021 Feb 18 '14 at 13:56
  • 1
    @GIJoe This answer is partial, but it complements Sneftel's well. – Pascal Cuoq Feb 18 '14 at 14:05
  • @GIJoe, why would it be *wrong*? The question asks for the purpose, and not about the origin of the definition. – Jens Gustedt Feb 18 '14 at 16:59
  • "This allows applications to use #ifdef, etc. to determine whether the macro is defined, but the macro is not usable in #if preprocessor directives because the preprocessor will treat the unexpanded word macro_name as having the value zero." – Engineer2021 Feb 18 '14 at 17:06
  • 1
    @GIJoe the quote does not contradict this answer. There is a difference between the preprocessor's interpretation of the macro in a `#if` directive versus elsewhere in the code (where it expands to the value of the enum). – Floris Feb 19 '14 at 01:10
  • Actually, it is affected by this answer. The way it is shown, the ifdef affects what code is executed between it, but thats not the case – Engineer2021 Feb 19 '14 at 01:50
8

The POSIX standard mandates that "symbolic constants" such as MSG_DONTROUTE be "object-like macros", rather than enumerants. Defining them to themselves allows them to be used in the context of the enumeration, as well as working properly with, e.g., #ifdef.

From the POSIX standard:

The header shall define the following symbolic constants .... MSG_DONTROUTE

And:

symbolic constant... refers to a C preprocessor symbol (also without arguments).

And finally, from an appendix:

Where a constant is required to be a macro but is also allowed to be another type of constant such as an enumeration constant, on implementations which do define it as another type of constant the macro is typically defined as follows:

#define macro_name macro_name

This allows applications to use #ifdef, etc. to determine whether the macro is defined, but the macro is not usable in #if preprocessor directives because the preprocessor will treat the unexpanded word macro_name as having the value zero.

Sneftel
  • 40,271
  • 12
  • 71
  • 104