Main C Header File Syntax

I am considering the math.h header included in my IDE. I see the following code, which I don't understand the syntax. This is basic stuff, but can anyone explain to me how it works?

#define isgreater(x,y) \
          (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
                           !isunordered(__x,__y) && (__x > __y);}))


So, for example, what does it do when you start something with double underscores, for example: Does __typeof

this allow undefined sizes? so this macro can take values ​​of different sizes?

Is the forward slash only line breaks in the source?

what does it do __extension__




source to share

2 answers

You can see the use of several compiler extensions:

  • __typeof__

    is a GCC extension that allows you to get the type of a variable (and use it in a variable declaration); it exists, so the macro can handle any type x

    and y

  • The second GCC extension turns ({ ... })

    into an expression that evaluates the value of the last statement within it; this allows you to declare variables inside that block, which avoids checking the two operands x

    and twice y

    . The results x

    and y

    (which might be something i++

    you don't want to evaluate twice) are stored in two temporary variables __x

    and __y

    , and then those two temporary variables are used instead of x

    and y

    to avoid double estimation.
  • __extension__

    is an extension that suppresses the warning you might otherwise use the above extension.

And yes, it \

just defines the definition of multiple lines of a macro ( \

concatenates the lines and is executed very early in the compilation process, even before the definitions of macros and preprocessors are discussed).

The whole point of this rigmarole is to avoid being evaluated x

and y

doubled. If you did

bool g = isgreater(x++, y++);


And you didn't use this trick, you get

bool g = !isunordered(x++, y++) && (x++ > y++);


This will lead to the fact that x

and y

will double every time, and not once, as you planned. Instead, with a trick, you end up with something like (using better names for temporary variables)

int tmpx = x++;
int tmpy = y++;
bool g = !isunordered(tmpx, tmpy) && (tmpx > tmpy);


(if x

and y

are integers), which is correct and avoids double increments. This goes for other things as well, like function calls:

isgreater(launch_missiles(3), launch_missiles(4));


Without the trick, you end up launching 14 missiles instead of 7, which would be disastrous.



This reformatting of the definition might help you

#define isgreater(x,y)                        \
(                                             \
  __extension__ (                             \
    {                                         \
      __typeof__(x) __x = (x);                \
      __typeof__(y) __y = (y);                \
      !isunordered(__x,__y) && (__x > __y);   \
    }                                         \
  )                                           \



marks code that uses gcc extension to the standard ANSI C. The expansion in this case is the operator __typeof__

that provides the type of a variable at compile time and is used to declare __x

and __y

with the same types as x

and y

. Then it goes ahead and checks that the pair of values ​​is ordered (which isunordered

is a Math library function) and is __x

greater than __y




All Articles