Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of defining a C macro to be itself? (seen in glibc headers)

On an Ubuntu Linux 20.04 machine, in /usr/include/x86_64-linux-gnu/bits/resource.h, I see code like this:

enum __rusage_who
{
  /* The calling process.  */
  RUSAGE_SELF = 0,
#define RUSAGE_SELF RUSAGE_SELF

  /* All of its terminated child processes.  */
  RUSAGE_CHILDREN = -1
#define RUSAGE_CHILDREN RUSAGE_CHILDREN
};

We see that RUSAGE_SELF is defined to be itself. What is the purpose/benefit of it?

enter image description here

like image 523
Jimm Chen Avatar asked Sep 03 '25 17:09

Jimm Chen


1 Answers

This is explained in the comment in the same file.

/* Transmute defines to enumerations.  The macro re-definitions are
   necessary because some programs want to test for operating system
   features with #ifdef RUSAGE_SELF.  In ISO C the reflexive
   definition is a no-op.  */

So they are just for feature testing with #ifdef to work.

You also want them to be actually usable as (compile-time) integral constant expressions. So #define RUSAGE_SELF will not work, you have to do #define RUSAGE_SELF RUSAGE_SELF.

The first sentence of the above comment indicates that it is very likely it was originally just #define RUSAGE_SELF 0. Indeed, for example this link contains the line #define RUSAGE_SELF 0.

However, although borderline opinion-based, defining integral constants as macros is inferior to using an enum for various reasons. See this question for details. As they need to be macros for feature testing with #ifdef, and after they decided to make the transition and rewrite them as enums, they need to ensure that those code are not broken by the change.

From the man page of getrusage(2), I can imagine someone may write the following code in order to be portable,

#ifdef RUSAGE_THREAD
if(getrusage(RUSAGE_THREAD, usage)==0){
    //Do something
}
else{
    //Error handling
}
#endif

This is necessary because RUSAGE_THREAD is only available in Linux >= 2.6.26. The only two choices that can make the above compile are

#define RUSAGE_THREAD 1

and

enum __rusage_who{
    //...
    RUSAGE_THREAD = 1;
#define RUSAGE_THREAD RUSAGE_THREAD
};

Since it has been decided that the latter is used, for the sake of consistency it makes sense to do the same for the other constants, including RUSAGE_SELF and RUSAGE_CHILDREN, although those two are guaranteed to be valid under POSIX.

like image 168
Weijun Zhou Avatar answered Sep 05 '25 07:09

Weijun Zhou



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!