Bug 之 隐式类型转换
请看
代码1(Linux GNU g++):
int nSendRet = -1;
size_t nDataSize = 5;
if(nSendRet > nDataSize) //Error
{
printf("nSendRet > nDataSize !!!!/n");
}
相关的生成汇编代码:
.LCFI2:
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $-1, -4(%ebp)
movl $5, -8(%ebp)
movl -4(%ebp), %eax
cmpl -8(%ebp), %eax
jbe .L2
subl $12, %esp
pushl $.LC0
.LCFI3:
call printf
addl $16, %esp
.L2:
movl $0, %eax
leave
ret
输出1:
nSendRet > nDataSize !!!!
代码2:
typedef unsigned long DWORD;
int main(void)
{
DWORD dwCurTick = 109;
DWORD m_dwLastInMsgTick = 110;
if(dwCurTick - m_dwLastInMsgTick > 150000)
{
printf("dwCurTick - m_dwLastInMsgTick > 150000, difference=%u/n", (dwCurTick - m_dwLastInMsgTick));
}
size_t i = 3 - 6;
printf("i=%u, sizeof(size_t)=%d/n", i, sizeof(size_t));
}
输出2:
dwCurTick - m_dwLastInMsgTick > 150000, difference=4294967295
i=4294967293, sizeof(size_t)=4
Why:
C++遇到两种不同数据类型的数值进行运算时,会将某个数做适当的类型转换,然后再进行转换。转换总是朝表达能力列强的方向进行,并且转换总是逐个运算符进行的。
以下是转换的两条方向线:
char/unsigned char --> short/unsigned short --> int/unsigned int --> double --> long double
float --> double --> long double
size_t是一种无符号的整型数, 在32位系统上 定义为 unsigned int(32位无符号整形)
它的意义大致是“适于计量内存中可容纳的数据项目个数的无符号整数类型”。
所以,它在数组下标和内存管理函数之类的地方广泛使用。
在int型和size_t进行比较时, 总是先将int转化为unsigned int然后再比较, 这个过程很可能不符合我们的要求, 导致条件判断错误。
[Summary]
要注意编译器的关于类型转换编译警告信息。