c - How to detect signedness with a macro? -
i trying detect if value of integer type family (char
, unsigned char
, short
, unsigned short
, int
, ...) negative number in c. if possible macro can compiled compliant c compiler (so, no gcc
-tricks allowed) , with no warning !
after time came following:
#define isneg(x) ((x) && (x-1) && ((x <= 0) && (~x >= 0)))
i tried following examples:
void display_result(int arg, int result) { printf("isneg(%d) %stive\n", arg, (result ? "nega" : "posi")); } void display_uresult(unsigned int arg, int result) { printf("isneg(%u) %stive\n", arg, (result ? "nega" : "posi")); } int main () { short shrt = 5; short nshrt = -5; unsigned short ushrt = 5; display_result(shrt, isneg(shrt)); display_result(nshrt, isneg(nshrt)); display_uresult(ushrt, isneg(ushrt)); int ni = -5; int = 5; int 0 = 0; display_result(ni, isneg(ni)); display_result(i, isneg(i)); display_result(zero, isneg(zero)); display_result(~zero, isneg(~zero)); // wrong unsigned int uzero = 0; unsigned int ui = 5; display_uresult(uzero, isneg(uzero)); display_uresult(~uzero, isneg(~uzero)); display_uresult(ui, isneg(ui)); long int li = -5; unsigned long int uli = 5; display_result(li, isneg(li)); display_uresult(uli, isneg(uli)); long long int lli = -5; unsigned long long int ulli = 5; display_result(lli, isneg(lli)); display_uresult(ulli, isneg(ulli)); return exit_success; }
and, result is:
isneg(5) positive isneg(-5) negative isneg(5) positive isneg(-5) negative isneg(5) positive isneg(0) positive isneg(-1) negative isneg(0) positive isneg(4294967295) positive isneg(5) positive isneg(-5) negative isneg(5) positive isneg(-5) negative isneg(5) positive
it works quite nice problem that, when compiled warnings (-wall -wextra
), following messages:
signedness.c: in function ‘main’: signedness.c:27:3: warning: promoted ~unsigned non-zero [-wsign-compare] display_uresult(ushrt, isneg(ushrt)); ^ signedness.c:4:49: warning: comparison of unsigned expression >= 0 true [-wtype-limits] #define isneg(x) ((x) && (x-1) && ((x <= 0) && (~x >= 0))) ^ signedness.c:41:26: note: in expansion of macro ‘isneg’ display_uresult(uzero, isneg(uzero)); ^ signedness.c:4:49: warning: comparison of unsigned expression >= 0 true [-wtype-limits] #define isneg(x) ((x) && (x-1) && ((x <= 0) && (~x >= 0))) ^ signedness.c:42:27: note: in expansion of macro ‘isneg’ display_uresult(~uzero, isneg(~uzero)); ^ signedness.c:4:49: warning: comparison of unsigned expression >= 0 true [-wtype-limits] #define isneg(x) ((x) && (x-1) && ((x <= 0) && (~x >= 0))) ^ signedness.c:43:23: note: in expansion of macro ‘isneg’ display_uresult(ui, isneg(ui)); ^ signedness.c:4:49: warning: comparison of unsigned expression >= 0 true [-wtype-limits] #define isneg(x) ((x) && (x-1) && ((x <= 0) && (~x >= 0))) ^ signedness.c:49:24: note: in expansion of macro ‘isneg’ display_uresult(uli, isneg(uli)); ^ signedness.c:4:49: warning: comparison of unsigned expression >= 0 true [-wtype-limits] #define isneg(x) ((x) && (x-1) && ((x <= 0) && (~x >= 0))) ^ signedness.c:55:25: note: in expansion of macro ‘isneg’ display_uresult(ulli, isneg(ulli)); ^
so, questions are:
is there better way detect have negative variable among possible integer types of c language ?
how rid of these warnings without deactivating (and without using gcc tricks) ?
this definition seems work me without warnings being generated:
#define isneg(x) (!((x) > 0) && ((x) != 0))
i used test cases macro on ideone.
if on system supports c.11's _generic
selection feature, can (this kind of simple minded, sure simplified exploiting integral promotion rules):
#define isneg(x) \ _generic((x), \ char: !((x) > 0) && (x) != 0, \ signed char: (x) < 0, \ short: (x) < 0, \ int: (x) < 0, \ long: (x) < 0, \ long long: (x) < 0, \ float: (x) < 0, \ double: (x) < 0, \ long double: (x) < 0, \ default: 0)
Comments
Post a Comment