C 迭代到一个非常大的数字 - 关于 unsigned int 的编译器警告

C iteration up to a very large number - compiler warning about unsigned int

我有以下代码:

#include <stdio.h>
#define POWER 10000000000000000000

int main()
{
    int i;
    for (i = 0; i < POWER; i++)
    {
         ....
    }
    return 0;
}

并且 编译器给我以下警告:

ex1.c:33:19: warning: integer constant is so large that it is unsigned [enabled by default] ex1.c:33:2: warning: this decimal constant is unsigned only in ISO C90 [enabled by default]

如何使用 i 运行 遍历所有值直到达到 POWER?我尝试将 i 声明为 unsigned int 但警告仍然存在。

10000000000000000000(= 10^19 如果我算对了)需要分配 64 位,这是 8 个字节。您收到警告是因为类型 int 使用 4 个字节,因此它无法存储该数字。使用 unsigned int 可以将最大正数加倍,但它是 4,294,967,295,这仍然不够。如果你想使用 int 你可以使用迭代循环。

    for(i=0;i<p;i++){
        for(j=0;j<p;j++){
            for(k=0<p;k++){
            /*loop*/
            }
        }
     }

其中 p 将是 intunsigned int,其值为 POWER 的立方根(在这种情况下,立方根无效,因为 19%3 != 0 并且 p 将不是 int ,它更像是一个想法而不是实际解决方案)

您的常数 10000000000000000000 需要 64 位来表示它。在十六进制中,它是 0x8ac7230489e80000。它可以用 unsigned 64 位类型表示,但不能用 signed 64 位类型表示。

从 C99 开始,所有整数常量都是某种有符号类型:intlong intlong long int 中第一个值适合的类型。

C90(还没有 long long int)有不同的规则。在 C90 中,无后缀的十进制整数常量的类型为 intlong intunsigned long int.

gcc 的默认模式是-std=gnu90,它支持C90 标准和GNU 特定的扩展。如果您使用的是 64 位系统,则 longunsigned long 是 64 位。根据 C90 规则,您的常量是 unsigned long 类型(假设 unsigned long 至少是 64 位)。在 C99 及更高版本的规则下,假设没有比 64 位宽的整数类型,这就是约束违规。 (gcc 版本 5 将默认值更改为 -std=gnu11。)

显然在 C90 规则下运行的编译器警告您 10000000000000000000 的含义因编译器在哪个版本的标准下运行而有所不同。

您可以通过以下更改使您的程序 "work":

#define POWER 10000000000000000000ULL // suffix to specify the type
...
for (unsigned long long = 0; i < POWER; i ++)
...

但是,尽管这使程序有效,但并不实用。以每纳秒一次迭代的速度,完成该循环将需要 3 个多世纪。我自己相当现代的计算机在大约 1.6 纳秒内执行一次 empty for 循环。无论您要解决什么问题,我都建议您要么找到一种不同的方法来解决它,要么将它简化为一个更小的问题。执行该循环的最快方法是等待几十年硬件变得更快,然后然后编译并执行它。

(这假设循环体是重要的。如果循环体什么都不做,编译器可能会完全优化循环。)