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

时间:2016-04-19 15:28:48

标签: c gcc compiler-warnings gcc-warning unsigned-integer

我有以下代码:

#include <stdio.h>
#define POWER 10000000000000000000

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

并且编译器给出了以下警告:

  

ex1.c:33:19:警告:整数常量太大,无符号[默认启用]   ex1.c:33:2:警告:此十进制常量仅在ISO C90中无符号[默认启用]

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

2 个答案:

答案 0 :(得分:4)

你的常量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的含义因编译器运行的标准版本而异。

您可以通过以下更改使您的程序“正常工作”:

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

但是,虽然这使程序有效,但它并不实用。在每纳秒一次迭代中,完成该循环需要3个多世纪。我自己的合理的现代计算机在大约1.6纳秒内执行 for循环的一次迭代。无论你想解决什么问题,我建议找到一种不同的方法来解决它,或者将它减少到一个较小的问题。执行该循环的最快方法是等待几十年,使硬件变得更快,然后然后编译并执行它。

(这假设循环的主体是非平凡的。如果循环的主体什么也不做,编译器可能会完全优化循环。)

答案 1 :(得分:-1)

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的立方根的vaue(在这种情况下,立方根无效为19%3!= 0且p不会是一个int,它更多的是一个想法,而不是一个实际的解决方案)