在阅读了这个关于有符号/无符号比较的问题之后(我会说他们每隔几天出现一次):
我想知道为什么我们没有正确的有符号无符号比较,而是这个可怕的混乱?从这个小程序中获取输出:
#include <stdio.h>
#define C(T1,T2)\
{signed T1 a=-1;\
unsigned T2 b=1;\
printf("(signed %5s)%d < (unsigned %5s)%d = %d\n",#T1,(int)a,#T2,(int)b,(a<b));}\
#define C1(T) printf("%s:%d\n",#T,(int)sizeof(T)); C(T,char);C(T,short);C(T,int);C(T,long);
int main()
{
C1(char); C1(short); C1(int); C1(long);
}
用我的标准编译器(gcc,64位)编译,我得到这个:
char:1
(signed char)-1 < (unsigned char)1 = 1
(signed char)-1 < (unsigned short)1 = 1
(signed char)-1 < (unsigned int)1 = 0
(signed char)-1 < (unsigned long)1 = 0
short:2
(signed short)-1 < (unsigned char)1 = 1
(signed short)-1 < (unsigned short)1 = 1
(signed short)-1 < (unsigned int)1 = 0
(signed short)-1 < (unsigned long)1 = 0
int:4
(signed int)-1 < (unsigned char)1 = 1
(signed int)-1 < (unsigned short)1 = 1
(signed int)-1 < (unsigned int)1 = 0
(signed int)-1 < (unsigned long)1 = 0
long:8
(signed long)-1 < (unsigned char)1 = 1
(signed long)-1 < (unsigned short)1 = 1
(signed long)-1 < (unsigned int)1 = 1
(signed long)-1 < (unsigned long)1 = 0
如果我编译为 32 位,结果是一样的,除了:
long:4
(signed long)-1 < (unsigned int)1 = 0
“怎么样?” 所有这些都很容易找到:只需转到 C99 标准的第 6.3 节或 C++ 的第 4 章,然后挖掘描述操作数如何转换为通用类型的子句,如果通用类型重新解释负值,这可能会中断。
但是“为什么?”呢?正如我们所见,'<' 在 50% 的情况下会失败,它还取决于类型的具体大小,因此它取决于平台。以下是需要考虑的几点:
转换和比较过程并不是最小惊喜规则的主要示例
我不相信那里有代码,它依赖于不是由恐怖分子编写的
(short)-1 > (unsigned)1
命题。当你在 C++ 中使用模板代码时,这一切都很糟糕,因为你需要类型特征魔法来编织一个正确的“<”。
毕竟,比较不同类型的有符号和无符号值很容易实现:
signed X < unsigned Y -> (a<(X)0) || ((Z)a<(Z)b) where Z=X|Y
如果可以静态证明 a>=0,则预检查很便宜,也可以由编译器优化掉。
所以这是我的问题:
如果我们添加安全的有符号/无符号比较 C/C++,它会破坏语言或现有代码吗?
(“它会破坏语言吗”意味着我们是否需要对语言的不同部分进行大量更改以适应这种变化)
更新: 我已经在我的旧 Turbo-C++ 3.0 上运行了这个并得到了这个输出:
char:1
(signed char)-1 < (unsigned char)1 = 0
为什么在(signed char)-1 < (unsigned char) == 0
这里?