【问题标题】:Is i=i+1 an undefined behaviour?i=i+1 是未定义的行为吗?
【发布时间】:2015-06-15 11:29:24
【问题描述】:

我正在使用代码块,它给其他编译器提供不同的输出,我找不到解决方案。这个程序中未定义的行为是什么,有什么解决方案可以避免它吗?

这是在只有 3 和 4 的数字系统中打印第 n 个数字的代码。

#include<stdio.h>                                                              
#include<math.h>                                                               
int main(void)                                                                 
{                                                                              
    int n,i,value;                                                             
    scanf("%d",&n);                                                            
    value=i=0;                                                                 
    while(n>0)                                                                 
    {                                                                          
        if((n%2)==0)                                                           
        {                                                                      
            value+=4*pow(10,i);                                                
        }                                                                      
        else                                                                   
        {                                                                      
            value+=3*pow(10,i);                                                
        }                                                                      
        n=(n-1)/2;                                                             
        i=i+1;                                                                 
    }
printf("\nThe number is : %d",value);                                                                          
}

它适用于最大 6 的数字。大于 6 的数字的输出比实际应该的少一。例如。如果 n=7,output=332 应该是 333。

编辑:提供带大括号的完整代码。

【问题讨论】:

  • 标题中问题的答案实际上取决于语言,它是如何设计和指定的。但总的来说,i = i + 1 是一个定义明确的操作。
  • 至于你的问题,它看起来像一些C代码,并且在C中缩进并不重要,这意味着所示sn-p中else部分的代码只是对@的赋值987654324@ 和其他两个语句在else 之外。
  • 总是使用大括号!除非你想在 Apple 工作,否则就是这样。
  • 提供实际代码!!
  • 也提示,'double pow(double x, double y)'

标签: c increment undefined-behavior


【解决方案1】:

您正在使用具有签名的函数 pow()

double pow(double x, double y);

并计算为 int。舍入/截断错误?

【讨论】:

    【解决方案2】:

    此代码中没有未定义的行为。 i=i+1; 是明确定义的行为,不要与提供未定义行为的 i=i++; 混淆。

    这里唯一可能导致不同输出的是floating point inaccuracy

    试试value += 4 * (int)nearbyint(pow(10,i));,看看有什么不同。

    【讨论】:

      【解决方案3】:

      似乎浮点数被截断了。

      【讨论】:

        【解决方案4】:

        这听起来像是一个编译器错误。 您将结果计算为value+=3*pow(10,i);,但这实际上转换为 value+= (int)(3*pow(10,i));

        这里可能有两件事之一是错误的:

        1. pow(10,0)!=1.0
        2. 强制转换为 int 会错误地截断结果。

        要轻松调试,只需尝试打印部分结果并查看问题所在。

        【讨论】:

          【解决方案5】:

          这里的问题很可能是这个特定平台上的pow 函数通过获取参数的对数(可能是自然对数;可能是对数基数 2),乘以指数,然后提高基数来执行其计算该产品的幂的第一个对数。对无限精度数执行这样的操作将产生数学上正确的结果,就像对扩展精度数执行操作并返回 double 结果一样。我的猜测是,此实现中使用的 pow 函数可能是为一个平台编写的,该平台可以使用扩展精度数字执行中间计算,因此会返回正确的双精度值,但它正在运行缺少扩展精度类型的平台。因此,pow(10,3) 可能会返回类似 999.9999999997 的内容,并将其强制为 int 会产生 999 而不是 1000。

          如果您试图获得整数类型的结果,则实际上没有理由将幂计算为浮点值。与其在循环中计算 10^i,不如让一个变量初始化为 1 并在每次循环中乘以 10。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-19
            • 1970-01-01
            • 2011-04-25
            • 2013-07-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-15
            相关资源
            最近更新 更多