对类型转换后比较的一点疑惑,详细请参看帖子。

wjlsmail 2007-11-21 05:39:50

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
int iData = -1;
unsigned int uiData = -1;
if (iData == uiData)
{
printf("==\n");
}
else
{
printf("Not run here\n");
}

long lData = -1;
unsigned long ulData = -1;
if (lData == ulData)
{
printf("==\n");
}
else
{
printf("Not run here\n");
}

long long llData = -1;
unsigned long long ullData = -1;
if (llData == ullData)
{
printf("==\n");
}
else
{
printf("Not run here\n");
}

///////////////////////////////////////////////////////////////////////////////////////////////
// 小于一个字长时
short sData = -1;
unsigned short usData = -1;

if (sData > usData)
{
printf("sData > usData\n");
}
else if (sData < usData)
{
printf("sData < usData\n");
}
else
{
printf("sData = usData\n");
}

char cData = -1;
unsigned char ucData = -1;

if (cData > ucData)
{
printf("cData > ucData\n");
}
else if (cData < ucData)
{
printf("cData < ucData\n");
}
else
{
printf("cData = ucData\n");
}

return 0;
}


在VS.Net2005环境下,结果是3个等于两个小于,为何呢?因为比较时的类型转换,应该都是等于才对。
和编译器相关? 那么别的编译器会是怎样的呢?

...全文
123 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjlsmail 2007-11-22
  • 打赏
  • 举报
回复
UP
wjlsmail 2007-11-22
  • 打赏
  • 举报
回复
To zenny_chen:

多谢回复。
对于后两个:short类型为16位,那么对于sData,它在比较前存入寄存器后的数据为0xffff_ffff。前面的4个f表示补码的符号位;而usData却是0x0000_ffff。这是因为它是无符号的短整型,所以表示成最大16位数。那么这样,两者通过带符号的比较可以得出,0xffff_ffff   <   0x0000_ffff。那么后面的char一样,对于8位数据,带符号仍表示为0xffff_ffff,而不带符号的可以表示为0x000000ff。这样得到的结果就是小于。


也就是在不足一个字长时,会补上符号位。这个可以理解。

对于一些基于GNU的C/C++编译器而言,如果出现一个带符号和一个不带符号的两个数的比较,那么编译器会有相应的warning。所以若要避免这样的warning,那么在比较时可以将其中一个数据类型强制转换一下。对于后两项,如果将前面的带符号类型强制转换为无符号的,那么结果就会相等。 


为什么要强制类型转换呢?按理说,在 if () 语句中,如果类型不一致,会自动向容量大的类型转换的----int, long, long long的结果也说明了这一点。



ar_2002 2007-11-22
  • 打赏
  • 举报
回复
mark
wangxipu 2007-11-21
  • 打赏
  • 举报
回复
4楼分析的很合理
xaobao 2007-11-21
  • 打赏
  • 举报
回复
LS说的真是精彩
zenny_chen 2007-11-21
  • 打赏
  • 举报
回复
原因说难也不难。只要对计算机了解一点,对数据编码格式有所了解的话就很容易解释。

首先,对于两个数的比较,计算机总是利用寄存器之间或寄存器和寄存器长的存储单元中的数据内容进行比较。如果你的PC机是32位的并且你的C/C++编译环境也是32位的,那么数据比较长度就是32位,也就是4个字节。下面我们就以32位为例:

前两个数据长度都是32位的(long和int)。那么对于iData和lData它们为-1,那么补码表示为0xffff_ffff。而对于ulData和uiData,它们是无符号的,所以转成-1时,它们的表示也为0xffff_ffff。虽然一个是带符号,另一个不带符号,但是比较时两个数据的值却是相同的,因此它们这样比较得出的结果为相同。
而对于long long类型,或者在VC中有__int64类型,它们被表示为64位数据不过这可能也是由两个寄存器拼起来的。不过不管怎样,它们都用足了寄存器长度,也就是32位。所以比较时和32位的一样。

对于后两个:short类型为16位,那么对于sData,它在比较前存入寄存器后的数据为0xffff_ffff。前面的4个f表示补码的符号位;而usData却是0x0000_ffff。这是因为它是无符号的短整型,所以表示成最大16位数。那么这样,两者通过带符号的比较可以得出,0xffff_ffff < 0x0000_ffff。那么后面的char一样,对于8位数据,带符号仍表示为0xffff_ffff,而不带符号的可以表示为0x000000ff。这样得到的结果就是小于。

对于一些基于GNU的C/C++编译器而言,如果出现一个带符号和一个不带符号的两个数的比较,那么编译器会有相应的warning。所以若要避免这样的warning,那么在比较时可以将其中一个数据类型强制转换一下。对于后两项,如果将前面的带符号类型强制转换为无符号的,那么结果就会相等。
比如:

if ((unsigned short)sData > usData)
{
printf("sData > usData\n");
}
else if ((unsigned short)sData < usData)
{
printf("sData < usData\n");
}
else
{
printf("sData = usData\n");
}


kingqin 2007-11-21
  • 打赏
  • 举报
回复
负数当然小于正数了。
HULIHONG 2007-11-21
  • 打赏
  • 举报
回复
和编译器没有关系,我想应该和你所用的机器有关。
wjlsmail 2007-11-21
  • 打赏
  • 举报
回复
UP

69,381

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧