今天玩力扣周赛中,遇到一个小小的坑。当然主要原因是自己掌握的知识不多,理解不够清楚。那就记录下来吧,希望以后不会再掉进去。
我们先来看一段代码,如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
string s = "hello";
for(int i = 0;i < s.size();i ++){
cout << s << endl;
}
return 0;
}
很简单的循环中输出语句,执行结果如下:
再看下面一段类似的代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
string s = "hello";
for(int i = -1;i < s.size();i ++){
cout << s[i];
}
return 0;
}
这段代码只是把i初始为-1,执行结果如下:
没有任何输出,很明显直接跳过了循环,乍一看,s.size()不是5吗,-1难道不小于5?
这里需要注意,std::size()返回无符号整型,而i是有符号整型-1,而负数在计算机中以补码形式存放,那么-1在内存中就是全1。同时,C语言中,当执行一个运算时,如果它的一个运算数是有符号的而另一个运算数是无符号的,那么C会隐含地将有符号数强制转换成无符号数。那下面就用几个例子说明,看看:
(1)、直接手动强制转换,把有符号转换成无符号
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
unsigned int a = -1;
cout << a;
return 0;
}
输出如下:()
(2)、遇到无符号和有符号同时运算,自动把有符号转换为无符号
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
unsigned int a = -1;
int b = 1;
cout << a + b << endl;
bool is_small = a < b;
cout << is_small;
return 0;
}
输出如下:
唉,等下,a + b = 0? 不是a强制转换成无符号了吗,怎么a + b还是0呢, a < b也为假。其实,-1在内存中的存放是这样的:11111111 11111111 11111111 11111111(补码),那么它对应的无符号那就是2^32 - 1,肯定大于1,若再加1,就会一直进位,直到溢出,最终为0。
好了,到这也就弄明白了,其实也就是一些小细节,如果我们最开始写成下面结构,就不会出现一些不必要的bug:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
string s = "hello";
int len = s.size();
for(int i = 0;i < len;i ++){
cout << s << endl;
}
return 0;
}
由此可见,每次coding时,需要养成良好的习惯,按照一定规范编写代码,能够避免掉一些不必要的麻烦,不仅提高效率,还利于后续的维护和更新迭代。