【问题标题】:Why Is Comparing if an Unsigned Int >= 0 a "Pointless Comparison"?为什么如果 Unsigned Int >= 0 进行比较是“毫无意义的比较”?
【发布时间】:2011-07-01 06:47:34
【问题描述】:

我收到警告:

Pe186“无符号整数与零的毫无意义的比较”

当我尝试编译以下代码时:

for(clLoop = cpLoopStart; clLoop >= 0; clLoop--)                                  
{
    //Do something
}

我不明白为什么。我可以理解,如果我正在寻找一个 小于 零的值,因为 unsigned int 永远不会是负数。但我在这里寻找的只是它是否等于为零,unsigned int 当然可以。

如果在这个循环中我尝试预先递减而不是后递减,我什至可以看到这个错误,但事实并非如此。

【问题讨论】:

  • 认为这样的错误消息可能取决于 pre 或 post(这里完全不相关)递增或递减是没有意义的—— clLoop 将采用任何一种方式的所有可能值。此外,如果 clLoop = 0 必须 也是无用的测试,因为 (clLoop = 0) .
  • 这就是while (clLoop--) { ... }更好的原因。

标签: c++ c for-loop comparison unsigned


【解决方案1】:

您检查 unsigned int 是否大于或等于 (>=) 零。这个表达式永远为真,因为无符号整数永远不会小于零。

编译器会尝试警告您将要编写一个无限循环。

【讨论】:

    【解决方案2】:

    您正在检查 unsigned int 是否等于或大于 0。这始终是正确的。

    【讨论】:

      【解决方案3】:

      无符号整数即使在无限递减之后也永远不会低于 0(即clLoop >= 0 将始终为真),这使得比较毫无意义。

      【讨论】:

        【解决方案4】:

        我想你是想说

        for(clLoop = cpLoopStart; clLoop; clLoop--)                                  
        { //Do something
        }
        

        【讨论】:

          【解决方案5】:

          clLoop >= 0 始终为真。无论您是预减量还是后减量,无符号值至少为 0。当您减少 0 时,您将得到 UINT_MAX

          编译器认为您可能意味着永远循环(或者您使用了不同的构造,更明显的是永远循环),因此发出警告。

          【讨论】:

            【解决方案6】:

            警告抱怨您的for 循环中断条件clLoop >= 0。如果clLoop 为负数,则循环将结束,但对于无符号整数永远不会发生这种情况。

            【讨论】:

              【解决方案7】:

              do{} while() 可以帮助你使用无符号类型的变量 for 循环而不会出现整数溢出:

              // main.c
              #include <stdio.h>
              
              int main(void)
              {
              
                  int array[] = {1,2,3,4,5,6,7,8,9,10};
                  unsigned int size = sizeof(array)/sizeof(int); // size == 10;
              
                  unsigned int i = size;
                  do
                  {
                      i--;
                      printf("Index: %u, content: %d\n",i,array[i]);
              
                  } while(i > 0);
              
                  return 0;
              }
              

              然后编译:

              gcc -std=c11 -Wall -Wextra -Wpedantic main.c
              

              输出:

              Index: 9, content: 10
              Index: 8, content: 9
              Index: 7, content: 8
              Index: 6, content: 7
              Index: 5, content: 6
              Index: 4, content: 5
              Index: 3, content: 4
              Index: 2, content: 3
              Index: 1, content: 2
              Index: 0, content: 1
              

              【讨论】:

                【解决方案8】:

                Centos 7 x86_64 中的 gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) 没有给出警告。

                但是当循环索引减少到-1 时,循环索引会隐式转换为等于 UINT_MAX (limits.h) 的值

                UINT_MAX + 1u is equal to 00 - 1 is equal to UINX_MAX.

                limits.h ANSI 提出的各种平台相关常量

                另一种解决方案是:

                unsigned int clLoop, i;
                
                for(i = cpLoopStart+1, clLoop = i-1; i > 0; i--, clLoop = i-1)                                  
                {
                    //Do something
                }
                

                i 将在 [1, cpLoopStart+1] 范围内变化

                clLoop 将在 [0, cpLoopStart] 范围内变化

                【讨论】:

                  【解决方案9】:

                  你应该在

                  中删除=
                  clLoop >= 0
                  

                  假设你的cpLoopStart is 5

                  那么,进一步迭代中的 clLoop 值将是 -

                  clLoop = 4;
                  clLoop = 3;
                  clLoop = 2;
                  clLoop = 1;
                  clLoop = 0;
                  clLoop = 0;
                  clLoop = 0;
                  clLoop = 0;
                  |
                  |
                  |
                  Infinite times.
                  

                  【讨论】:

                    【解决方案10】:

                    正如其他人已经说过的那样 unsigned int 总是 >= 0 即毫无意义的比较。 Mayank Jindal 为我发布了解决方案的起点。

                    要将“修复”作为一个整体记录:请改为执行以下操作,这将按预期工作:

                    unsigned int cpLoopStart = 23U;
                    unsigned int clLoop = 0U;
                    for(clLoop = cpLoopStart; clLoop > 0U; clLoop--}
                    {
                        //Do something
                    }
                    

                    clLoop 将从 23 开始并在 1 结束,然后退出循环。我希望 clLoop 在循环内永远不会为 0。

                    我也更喜欢为无符号类型的值附加“U”,这在比较值和变量时也更清楚。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2020-08-28
                      • 2018-05-09
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-07-02
                      • 2013-06-15
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多