3

The Linux kernel defines a number of helper macros for type neutral numeric operations. Namely the macros min and max are defined as (in include/linux/kernel.h)

#ifndef max
#define max(x, y) ({ \
        typeof(x) _max1 = (x); \
        typeof(y) _max2 = (y); \
        (void) (&_max1 == &_max2); \
        _max1 > _max2 ? _max1 : _max2; })
#endif
#ifndef min
#define min(x, y) ({ \
        typeof(x) _min1 = (x); \
        typeof(y) _min2 = (y); \
        (void) (&_min1 == &_min2); \
        _min1 < _min2 ? _min1 : _min2; })
#endif

When expanded they produce anonymous functions that perform the operation type neutral and in-expression-assigment safe way (using GCC anonymous functions). So far so good. What surprised me is the second to last expression produced by these macros:

   (void) (&_min1 == &_min2);

The addresses of the temporary variables defined within the scope of the anonymous function are compared and the result then discarded; the (void) cast preventing any warnings to show up.

I wonder what the desired side effect of this is? Naively I'd expect this to get optimized away, since it has no side effects (at least none I am aware of).

datenwolf
  • 159,371
  • 13
  • 185
  • 298

1 Answers1

2

The compiler will complain for the == if both variables don't have the same type. So I suspect this is to ensure the values really can be compared.

Try:

int i;
char *p;
(void)min(i, p);

And yes, the operation will be optimised away with any optimisation level other than -O0.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • Oh! Of course. :) – OTOH: I wonder how much sense this makes? For example I see no problem comparing a, say, `signed long` with a `signed char`, as per the integer promotion rules the operation promotes the `signed char` to `signed long`. And I can think of a lot of cases where one might want to perform a comparison like that. – datenwolf Feb 08 '16 at 17:10
  • @datenwolf: Problem is, you have all or nothing here. Without that you can also compare e.g.`int` and pointers because of conversion rules. Maybe this was more necessary with older compilers (pre-C99) which were much less trigger-happy (and had much less options to request warnings, too). If you want to compare compatible types, you still can cast an argument, even with `typeof()`. – too honest for this site Feb 08 '16 at 17:20
  • 1
    @machine_1: Do not change correct syntax. – too honest for this site Feb 08 '16 at 19:37