RSS | technovelty home | page of ian | ianw@ieee.org
The canonical definition of max is something like
#define max(a,b) ( ( (a) >= (b) ) ? (a) : (b))
But this raises many issues with types in C. What if you pass in
an unsigned int and a signed int all at the
same time? Under what circumstances is the comparison valid? What
type should be returned?
The kernel gets around this by being tricky
/*
* min()/max() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
*/
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
The give you a clue to how this works by talking about the pointer
comparison. C99 6.5.9.2 says that for the == comparison
Both operands are pointers to qualified or unqualified version of compatible types
Where compatible types are defined in 6.7.2.1
Two types have compatible type if their types are the same.
There are additional rules, but gcc is right to warn
you when you compare pointers of incompatible types. Note that if the
inputs are not pointers, but arithmetic types, the C99 standard
says that normal arithmetic conversions apply. You can see that the
outcome of this is really probably not what you want, but the compiler
has no reason to warn you.
Thus the above code makes a warning spew out if you try to compare values of incompatible types. You can try it yourself
$ cat test.c
#include <stdio.h>
int main(void)
{
int i = -100;
unsigned int j = 100;
if (&i == &j);
if (i < j)
printf("OK\n");
if (i > j)
printf("i is -100, why is that > 100?\n");
return 0;
}
$ gcc -Wall -o test test.c
test.c: In function 'main':
test.c:8: warning: comparison of distinct pointer types lacks a cast
$ ./test
i is -100, why is that > 100?
Not the most straight forward warning in the world, but sufficient to let you know you're doing something wrong. Note we don't get any warning where the problem really is, except we get a value we don't expect. C certainly can be a very tricky language to get right!
posted at: Thu, 08 Dec 2005 17:19 | in /code/c | permalink | add comment (0 others)

This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.