【发布时间】:2013-08-19 23:17:09
【问题描述】:
我正在尝试检测整数类型系列的值(char、unsigned char、short、unsigned short、int,...)是否是 C 中的负数。如果可能的话一个可以用任何兼容的 C 编译器编译的宏(因此,不允许使用 gcc-tricks)并且没有警告!
一段时间后,我带来了以下内容:
#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 技巧)的情况下消除所有这些警告?
【问题讨论】:
-
@WhozCraig:我说的不是变量的类型,而是变量的值。此外,给定一个变量,C 没有自省,因此无法“先验”获取变量的类型(除非您使用的是非标准扩展)。
-
(X < 0)有什么问题?是无符号类型的编译器警告吗? -
原谅我。开场白,“我正在尝试检测 C 中是否为整数类型”,让我大吃一惊。
-
@jxh:当 X 为
unsigned时,它将在编译时引发警告。我不想发出警告,因为我们正在使用-Werror进行编译。
标签: c c-preprocessor signed