Я пытаюсь обнаружить, если значение целого типа семейства (char
, unsigned char
, short
, unsigned short
, int
, ...) является отрицательным числом С. Если возможно с помощью макроса, который может быть собран с любым совместимым компилятором (так, нет разрешенных gcc
) и без предупреждения!Как обнаружить подпись с макросом?
Через некоторое время я пришел с следующее:
#define ISNEG(X) ((X) && (X-1) && ((X <= 0) && (~X >= 0)))
Я пробовал со следующими примерами:
void
display_result(int arg, int result)
{
printf("ISNEG(%d) is %stive\n", arg, (result ? "nega" : "posi"));
}
void
display_uresult(unsigned int arg, int result)
{
printf("ISNEG(%u) is %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 i = 5;
int zero = 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;
}
И результат:
ISNEG(5) is positive
ISNEG(-5) is negative
ISNEG(5) is positive
ISNEG(-5) is negative
ISNEG(5) is positive
ISNEG(0) is positive
ISNEG(-1) is negative
ISNEG(0) is positive
ISNEG(4294967295) is positive
ISNEG(5) is positive
ISNEG(-5) is negative
ISNEG(5) is positive
ISNEG(-5) is negative
ISNEG(5) is positive
Он работает довольно неплохо, но проблема в том, что при составлении всех предупреждений (-Wall -Wextra
) я получаю следующее Крыло сообщение:
signedness.c: In function ‘main’:
signedness.c:27:3: warning: promoted ~unsigned is always non-zero [-Wsign-compare]
display_uresult(ushrt, ISNEG(ushrt));
^
signedness.c:4:49: warning: comparison of unsigned expression >= 0 is always 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 is always 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 is always 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 is always 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 is always 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));
^
Итак, мои вопросы:
Есть ли лучший способ определить, что мы имеем отрицательную переменные среди всех возможных целочисленных типов языка C?
Как избавиться от всех этих предупреждений без его деактивации (и без использования трюков GCC)?
Возможный дубликат [Макро, чтобы проверить, является ли заданный целочисленный тип подписанным или незаписанным в C?] (Http://stackoverflow.com/questions/7962855/macro-to-test-whether-a-given- integer-type-is-signed-or-unsigned-in-c) – WhozCraig
@WhozCraig: Я не говорю о типе переменной, а о значении переменной. Более того, учитывая переменную, C не имеет интроспекции, поэтому нет способа получить тип переменной «априори» (за исключением случаев, когда вы используете нестандартное расширение). – perror
Что не так с '(X <0)'? Это предупреждение компилятора для неподписанных типов? – jxh