疯了,为什么我的变量会改变我?

时间:2011-09-15 03:42:58

标签: c++ c debugging testing

好吧,我之前发生了这种情况,因为内存分配问题或错误的寻址等因素导致变量随机改变数字,例如当你超出数组范围时。但是,我没有使用数组,指针或地址,所以我不知道为什么在执行这个循环后它突然决定设置为0后的“exponent”等于循环内的288

编辑:它决定专门打破:0x80800000

这在一次测试中没有中断,我们有一个“测试”客户端,它遍历几个测试用例,每次再次调用它时,每次再次调用该函数时,值应该是设置等于原始值。

/* 
 * float_i2f - Return bit-level equivalent of expression (float) x
 *   Result is returned as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point values.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_i2f(int x) { 
    int sign= 0;
    int a=0;
    int exponent=0;
    int crash_test=0;
    int exp=0;
    int fraction=0;
    int counter=0;

    if (x == 0) return 0;
    if (!(x ^ (0x01 << 31)))
    {
        return 0xCF << 24;
    }
    if (x>>31)
    {
        sign = 0xFF << 31;
        x = (~x) + 1;
    }
    else
    {
        sign = 0x00;
    }
    //printf(" After : %x  ", x);

    a = 1;
    exponent = 0;
    crash_test = 0;
    while ((a*2) <= x)
    {
        if (a == 0) a =1;
        if (a == 1) crash_test = exponent;
        /*
        if(exponent == 288) 
        {exponent =0;
            counter ++;
            if(counter <=2)
            printf("WENT OVERBOARD WTF %d  ORIGINAL %d", a, crash_test);
        }
        */
        if (exponent > 300) break;

        exponent ++;
        a *= 2;
    }

    exp = (exponent + 0x7F) << 23;
    fraction = (~(((0x01)<< 31) >> 7)) & (x << (25 - (exponent + 1)));
    return sign | exp | fraction;
}

7 个答案:

答案 0 :(得分:2)

使用调试器或IDE,在指数值上设置监视/断点/断言(例如 (exponent > 100)

调用 float_i2f() 的x的违规值是多少?所有x或某个范围的指数是否爆炸?

(你刚才说x = 0x80800000吗?你是否设置了一个关于指数的监视并在调试器中为该值设置步骤?应该回答你的问题。例如,你检查了0x807FFFFF的工作原理吗?)

答案 1 :(得分:0)

我自己尝试使用Visual Studio,并输入“10”,它似乎工作正常。

问:在失败的情况下,你能给我一个“x”的输入值吗?

问:你用的是什么编译器?你在运行什么平台?

答案 2 :(得分:0)

你的行在while循环结束时递增指数。

while((a*2) <= x)
{
    if(a == 0) a =1;
    if(a == 1) crash_test = exponent;
    /* 

    if(exponent == 288) 
    {
        exponent =0;
        counter ++;
        if(counter <=2)
        printf("WENT OVERBOARD WTF %d  ORIGINAL %d", a, crash_test);
    }
    */

    if(exponent > 300) break;

    exponent ++;
    a *= 2;

}

答案 3 :(得分:0)

在那里有很多无用的优化尝试,我已经删除了它们,因此代码更容易阅读。我也酌情使用了<stdint.h>种类型。

循环中a *= 2中有符号整数溢出,但主要问题是缺少常量和奇怪的魔数计算。

这仍然不是示例性的,因为常量应该都被命名,但这似乎可靠地起作用。

#include <stdio.h>
#include <stdint.h>

uint32_t float_i2f(int32_t x) { 
    uint32_t sign= 0;
    uint32_t exponent=0;
    uint32_t fraction=0;

    if (x == 0) return 0;
    if ( x == 0x80000000 )
    {
        return 0xCF000000u;
    }
    if ( x < 0 )
    {
        sign = 0x80000000u;
        x = - x;
    }
    else
    {
        sign = 0;
    }

    /* Count order of magnitude, this will be excessive by 1. */
    for ( exponent = 1; ( 1u << exponent ) <= x; ++ exponent ) ;

    if ( exponent < 24 ) {
        fraction = 0x007FFFFF & ( x << 24 - exponent ); /* strip leading 1-bit */
    } else {
        fraction = 0x007FFFFF & ( x >> exponent - 24 );
    }
    exponent = (exponent + 0x7E) << 23;
    return sign | exponent | fraction;
}

答案 4 :(得分:0)

变量exponent没有做任何神秘的事情。您每次循环都会递增exponent,因此它最终会达到您喜欢的任何数字。真正的问题是为什么你的循环在你认为应该退出时不会退出?

您的循环条件取决于a。尝试在循环重复时打印出a的连续值。你注意到a到达1073741824后发生了什么有趣的事吗?您是否听说过班级中的整数溢出?

答案 5 :(得分:0)

只需处理“a”变为负数的情况(或更好,验证您的输入,以便它在第一时间永远不会变为负数),您应该没问题:)

答案 6 :(得分:0)

a溢出。 a*2==0 a==1<<31exponent%32==0,每次a==0exponent==300并循环到fraction

还有一些其他问题:

exponent>=241计算已关闭。负左移不会自动转为正向右移。

生成分数的掩码也略有错误。始终假定前导位为 fraction = (~(((0x01)<< 31) >> 8)) & (x << (24 - (exponent + 1))); ,并且尾数仅为23位,因此x <2 ^ 23的分数应为:

exponent

计算abs(x)>=1<<31的循环在1时失败(如果不适当地舍入,则偶然会导致精度损失);将隐式{{1}}考虑在内的循环在这里会更好。