我疯了,为什么我的变量对我变了

Going crazy, why are my variables changing on me?

本文关键字:变量 我变了 我的 为什么 疯了      更新时间:2023-10-16

好吧,我有这种情况发生在我之前,其中变量随机改变数字,因为内存分配问题或错误的寻址等,比如当你走了边界与数组。然而,我没有使用数组,或指针或地址,所以我不知道为什么在执行这个循环后,它突然决定"指数"设置为0后等于循环内的288:

EDIT:它决定在特定的: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;
}

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

float_i2f() 调用时x的违规值是什么?指数是否对所有x,或某个范围都起作用?你刚才是不是说当x = 0x80800000 ?你是否对指数设置了监视,并在调试器中对该值执行步骤?应该能回答你的问题。例如,您是否检查0x807FFFFF是否有效?)

我自己用Visual Studio试过了,输入"10",看起来还行。

Q:你能给我一个"x"的输入值吗?

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

在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;
}

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

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

只要处理"a"为负的情况(或者更好的是,验证您的输入,使其永远不会在第一个地方为负),您应该没问题:)

这里有许多无用的优化尝试,我已经删除了它们,以便代码更容易阅读。我还使用了<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;
}

a溢出。a*2==0a==1<<31,所以每次exponent%32==0, a==0和你循环直到exponent==300

还有一些其他的问题:

exponent>=24时,fraction计算关闭。负的左移不会自动转换为正的右移。

生成分数的掩码也有一点错误。前导位总是被假定为1,尾数只有23位,所以x<2^23的分数应该是:

    fraction = (~(((0x01)<< 31) >> 8)) & (x << (24 - (exponent + 1)));

计算exponent的循环在abs(x)>=1<<31时失败(如果没有适当舍入,会顺便导致精度损失);考虑隐式1的循环在这里会更好。

相关文章: