【问题标题】:Warning message when using pow() function in C programming language在 C 编程语言中使用 pow() 函数时出现警告消息
【发布时间】:2015-04-07 04:57:39
【问题描述】:

我正在编写一个非常基本的程序来打印 C 语言中 unsigned long long 变量的范围(0 到 ((2 ^ n) - 1),其中 n 是任何系统中的数据类型(其中安装了 C 并根据编译器)。在我的系统中,long long 变量的大小为 8 个字节。

我正在使用以下代码:

#include<stdio.h>
#include<math.h>

int main()
{
   unsigned long long n;

   //n = pow(2, 63);
   //n = (n * 2) - 1;
     n = pow(2, 64) - 1;    

     printf("\nn: %llu\n", n);

     return 0;
}

在编译时,gcc 给了我以下错误:

Print_long_long_int.c:10:2:警告:隐式常量转换溢出 [-Woverflow]。

在执行它时,我得到了正确的输出 号码:18446744073709551615

但是,如果我从行中删除单个 cmets 并使用它们:

n = pow(2, 63);
n = (n * 2) - 1;

代替:

n = pow(2, 64) - 1;

它没有给我任何这样的警告。并正常执行。 为什么会出现这种差异?

谢谢!

【问题讨论】:

  • 这可能意味着 GCC 没有在运行时调用 pow(),而是在编译时评估常量,它注意到 pow(2, 64) 太大而无法放入 64 位无符号整数,但是并没有拒绝完成编译,并且确实通过一些或多或少的迂回手段得到了正确的答案。其他编译器或优化较少的 GCC 可能会做不同的事情。
  • pow 根本不是该任务的正确工具,它适用于 double 而不适用于整数类型。所以在任何时候你都可能失去精度。使用移位运算符&lt;&lt; 获得2 的大幂。但即便如此,如果您的类型只有 64 位,您显然无法获得高于 63 的功率。

标签: c pow


【解决方案1】:

当你给予时

 pow(2,64) -1 ;

它超出了 unsigned long long 的限制。这就是您收到该警告的原因。

无符号长整数的范围是0 to 18,446,744,073,709,551,615

pow(2,64) 的结果是18446744073709551616

【讨论】:

  • 如果是这样的话,为什么会有这样的行:n = pow(2, 63); n = (n * 2) - 1;作品?因为执行这两行给了我 n: 18446744073709551615 的正确答案。如果unsigned long long的大小比较小,这两行不应该也弹出警告信息吗?
【解决方案2】:

Power 应该返回一个整数,而你得到一个 unsigned long long。我只是做了一个简单的幂函数来处理 unsigned long longs。

#include<stdio.h>

unsigned long long power(int base, int exponent)
{
    unsigned long long n = 1;
    int i;
    for (i = 0; i < exponent ; i++)
        n *= base;

    return n;
}

int main()
{
unsigned long long n = power(2, 64) - 1; 
printf("n: %llu\n", n);

return 0;
}

【讨论】:

  • 不应该unsigned long long n = 1(在“power”的函数定义中),因为如果为0,则整个乘积将计算为0。
  • 是的,你是对的。我写的很匆忙,犯了一个粗心的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-21
  • 2022-10-14
  • 1970-01-01
  • 2018-01-01
  • 2018-05-25
相关资源
最近更新 更多