A “bug”
今天在做codeforces 223B http://codeforces.com/problemset/problem/223/B 的时候遇到一个很隐蔽的“bug”,欣喜之余,把它记录下来。
把遇到的问题提取出来,就是下面这段代码:
#include <iostream> #include <string> int main() { std::string str("abc"); if(-1 < str.length()) { std::cout << "Yes" << std::endl; } else { std::cout << "No" << std::endl; } return 0; }
这段代码的输出是Yes还是No呢?
表面上看,str.length()应该是3;-1小于3是true,那么应该输出Yes。
然而你编译运行下这段代码就会发现,它输出的并不是Yes,而是No,为什么呢?
我们看一下str.length()返回的是什么。众所周知,str.length()返回字符串的长度 ,然而关注返回值类型的人比较少,它的类型是size_t,在cstddef中,size_t定义为unsigned int。-1的类型是int,在int和unsigned比较前需要将数据类型提升一致。于是就把-1转化成unsigned类型,而-1在内存中存储为0xffffffff(32位),于是unsigned(-1)=0xffffffff=232-1了,那么表达式232-1<3必然为false,于是输出No
2012年9月24日 23:10
你不是用 gcc 编译的么?
>>> g++ -Wall a.cxx
a.cxx: 在函数‘int main()’中:
a.cxx:7:24: 警告:在有符号和无符号整数表达式间比较 [-Wsign-compare]
2012年10月09日 23:59
是的,有些是有警告,不过警告不影响生成可执行文件的吧@依云:
2012年10月10日 09:12
@hustsxh: 但是警告指出了问题所在啊。你不说它「很隐蔽」么?gcc 给我揪出来了。
2012年10月10日 11:05
@依云: 之前还不清楚Wall这个参数,直接 g++ -o X X.cpp了,所以没有显示警告,这里学习了。再则与string::length比较的是一个表达式,对出现负值也没有特别注意。很“隐蔽”都是因为我知识有限造成的,见笑了