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:

  1. is there better way detect have negative variable among possible integer types of c language ?

  2. 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

Popular posts from this blog

java - JavaFX 2 slider labelFormatter not being used -

Detect support for Shoutcast ICY MP3 without navigator.userAgent in Firefox? -

web - SVG not rendering properly in Firefox -