• C++ | 使用 xxx.size() 作为循环条件的问题


    问题代码

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s="a";
    
        printf("%d
    ",s.size()-5);
        cout<<s.size()-5<<endl;
    
        for(int i=0;i<=s.size()-5;i++)
            printf("ViVid-BinGo
    ");
    
        system("pause");
        return 0;
    }

      

      以上是问题代码的运行结果,这时就会有问题出现了。

      ① 字符串 s 的大小为 1 ,那么 s.size() - 5 == -4。但是用 printf("%d") 和 cout 输出 s.size() - 5 的结果分别为 -4 和 18446744073709551612 ,显然结果并不相同。

      ② 不严谨的说,for循环中判断条件 0 <= -4 显然不成立,那么一句 “ViVid-BinGo” 也不会输出。但是通过运行结果可以看出,“ViVid-BinGo” 被输出出来了,而且不止输出了一次。

    解决

      可以从C++参考手册中看到,s.size() 的返回值为无符号整型。那么我们可以想到,与 s.size() 进行运算的 -5 是个有符号整型。

      当出现不同类型的变量参与运算时,那么低级类型会向上转换以至于达到同一个类型,在这里因为无符号类型比有符号类型级别高,所以 -5 应该先转换到无符号类型,然后再和 s.size() 运算。

      有无符号数转换规则:

        ① 有符号数转换为无符号数时,负数转换为大的正数,相当于在原值上加上2^n,而正数保持不变。

        ② 无符号数转换为有符号数时,对于小的数将保持原值,对于大的数将转换为负数,相当于原值减去2^n。

    第一个问题

      根据有无符号数转换规则可以得出:

         -5 ---> -5 + 2^64 = 18446744073709551611‬,再加上 s.size() = 1,所以 18446744073709551611‬ + 1 = 18446744073709551612

      所以 s.size() - 5 = 18446744073709551612。

      因为使用 printf("%d") 进行输出的时候,因为“%d”的缘故,有一个强制类型转换,即将无符号类型转换成有符号类型,所以 18446744073709551612 - 2^64 = -4,所以printf输出的是 -4.

      然而在使用 cout 输出的时候没有类型转换,则直接输出,那么输出的就是 18446744073709551612 。

    第二个问题

      如果第一个问题解决了,那么第二个问题就解决了。

      因为在 for 循环中,s.size() - 4 没有进行类型转换,所以等价于下面的 for 循环

      for(i = 0 ; i <= 18446744073709551612 ; i++)

      所以程序运行结果中 “ViVid-BinGo”才会被打印出来。

    总结

    废话不多说。

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s="a";
    
          printf("%d
    ",s.size()-5);
        cout<<s.size()-5<<endl;
        
        int len=s.size()-5;
        for(int i=0;i<=len;i++)
            printf("ViVid-BinGo
    ");
    
        system("pause");
        return 0;
    }
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        string s="a";
    
          printf("%d
    ",s.size()-5);
        cout<<s.size()-5<<endl;
    
        for(int i=0;i<=(int)s.size()-5;i++)
            printf("ViVid-BinGo
    ");
    
        system("pause");
        return 0;
    }
  • 相关阅读:
    小节 +三元表达式
    continue
    break
    flag标签
    #region #endregion
    for 循环
    do while 有例句体会循环的真正原理
    while 循环
    前缀和与差分
    递归的循环实现
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/12241945.html
Copyright © 2020-2023  润新知