/* * Test cases for comparing results of different min()/max() implementations * with different compilers. -- Mike A. Harris * * Compile with: gcc -Wall -o minmax minmax.c */ #include /* * gccmin()/gccmax() macros are replacements for min()/max() which perform * strict type checking using gcc's typeof extension, and prevent double * execution of arguments. */ #define gccmin(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x < _y ? _x : _y; }) #define gccmax(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x > _y ? _x : _y; }) /* * gccminnoprot()/gccmaxnoprot() macros are replacements for min()/max() * which perform strict type checking using gcc's typeof extension, but * do NOT prevent double execution of arguments. */ #define gccminnoprot(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x < _y ? (x) : (y); }) #define gccmaxnoprot(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x > _y ? (x) : (y); }) /* * min()/max() are traditional versions of these macros without type * checking or multiple execution protection. These would be used in the * case where gcc isn't available. */ #define min(x,y) ((x) < (y) ? (x) : (y)) #define max(x,y) ((x) > (y) ? (x) : (y)) /* Convenience macros */ #define set_ab() (a = 10, b = 20) #define set_xy() (x = 10, y = 20) int main(void) { int a, b, x; long y; printf("Test cases for same-type comparisons:\n"); set_ab(); printf("Traditional min/max without side effects: min(a,b)=%d, max(a,b)=%d\n", min(a,b), max(a,b)); set_ab(); printf("gccmin/gccmax without side effects : min(a,b)=%d, max(a,b)=%d\n", gccmin(a,b), gccmax(a,b)); set_ab(); printf("Traditional min with side effects : min(a++,b++)=%d\n", min(a++,b++)); set_ab(); printf("Traditional max with side effects : max(a++,b++)=%d\n", max(a++,b++)); set_ab(); printf("gccmin with side effects : min(a++,b++)=%d\n", gccmin(a++,b++)); set_ab(); printf("gccmax with side effects : max(a++,b++)=%d\n", gccmax(a++,b++)); printf("\nTesting for mismatched type in min/max comparisons.\n"); set_xy(); printf("Traditional min/max without side effects: min(x,y)=%ld, max(x,y)=%ld\n", min(x,y), max(x,y)); set_xy(); printf("gccmin/gccmax without side effects : min(x,y)=%ld, max(x,y)=%ld\n", gccmin(x,y), gccmax(x,y)); /* gcc issues warning at compile time here */ set_xy(); printf("Traditional min with side effects : min(x++,y++)=%ld\n", min(x++,y++)); set_xy(); printf("Traditional max with side effects : max(x++,y++)=%ld\n", max(x++,y++)); set_xy(); printf("gccmin with side effects : min(x++,y++)=%ld\n", gccmin(x++,y++)); /* gcc issues warning at compile time here */ set_xy(); printf("gccmax with side effects : max(x++,y++)=%ld\n", gccmax(x++,y++)); /* gcc issues warning at compile time here */ printf("\nTesting for mismatched type in min/max comparisons without double exec protection.\n"); set_xy(); printf("Traditional min/max without side effects : min(x,y)=%ld, max(x,y)=%ld\n", min(x,y), max(x,y)); set_xy(); printf("gccmin/gccmax noprot without side effects: min(x,y)=%ld, max(x,y)=%ld\n", gccminnoprot(x,y), gccmaxnoprot(x,y)); /* gcc issues warning at compile time here */ set_xy(); printf("Traditional min with side effects : min(x++,y++)=%ld\n", min(x++,y++)); set_xy(); printf("Traditional max with side effects : max(x++,y++)=%ld\n", max(x++,y++)); set_xy(); printf("gccminnoprot with side effects : min(x++,y++)=%ld\n", gccminnoprot(x++,y++)); /* gcc issues warning at compile time here */ set_xy(); printf("gccmaxnoprot with side effects : max(x++,y++)=%ld\n", gccmaxnoprot(x++,y++)); /* gcc issues warning at compile time here */ return 0; }