C++ 发疯了,为什么我的变量在我身上发生变化?
好吧,我以前也遇到过这种情况,变量会因为内存分配问题或错误的寻址等而随机改变数字,比如当你使用数组越界时。但是,我没有使用数组、指针或地址,所以我不知道为什么在执行此循环后,它突然决定在循环中设置为C++ 发疯了,为什么我的变量在我身上发生变化?,c++,c,debugging,testing,C++,C,Debugging,Testing,好吧,我以前也遇到过这种情况,变量会因为内存分配问题或错误的寻址等而随机改变数字,比如当你使用数组越界时。但是,我没有使用数组、指针或地址,所以我不知道为什么在执行此循环后,它突然决定在循环中设置为0后的“指数”等于288: 编辑:它决定专门打开:0x80800000 这不会在一个测试中中断,我们有一个“测试”客户机,它迭代多个测试用例,每次它再次调用它,每次再次调用函数时,值应设置为等于其原始值 /* * float_i2f - Return bit-level equivalent of
0
后的“指数”等于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;
}
/*
*float_i2f-表达式(float)x的返回位级等效值
*结果返回为无符号整数,但
*它将被解释为一个字节的位级表示
*单精度浮点值。
*合法运算:任何整数/无符号运算,包括| |、&&。也如果
*最多运行时间:30
*评级:4
*/
无符号浮点i2f(int x){
int符号=0;
int a=0;
int指数=0;
int crash_试验=0;
int exp=0;
整数分数=0;
int计数器=0;
如果(x==0)返回0;
如果(!(x^(0x01 31)
{
sign=0xFF使用调试器或IDE,在指数值上设置监视/断点/断言(例如(指数>100)
)
调用float_i2f()
时使用的x的值是多少?指数是针对所有x还是某个范围爆炸的
(你刚才是说当x=0x80800000时吗?你是不是在指数上设置了一个手表并在调试器中为该值步进?应该可以回答你的问题。例如,你是否检查了0x807FFFFF是否工作?)我自己用Visual Studio试过,输入了“10”,它似乎工作正常
问:如果失败,你能给我一个输入值“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;
}
虽然((a*2)其中有许多无用的优化尝试,但我已经删除了它们,以便代码更易于阅读。此外,我还酌情使用了
类型
循环中的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;
}
#包括
#包括
uint32浮点数i2f(int32浮点数x){
uint32\u t符号=0;
uint32_t指数=0;
uint32_t分数=0;
如果(x==0)返回0;
如果(x==0x8000000)
{
返回0xCF000000u;
}
if(x<0)
{
符号=0x80000000u;
x=-x;
}
其他的
{
符号=0;
}
/*计算数量级,这将超出1*/
对于(exponent=1;(1u变量exponent
没有做任何神秘的事情。每次循环中,你都在增加exponent
,因此它最终会命中你喜欢的任何数字。真正的问题是,为什么你的循环没有在你认为应该退出的时候退出
循环条件取决于a
。在循环重复时,请尝试打印出a
的连续值。在a
达到1073741824后,您是否注意到有什么有趣的事情发生?您听说过类中存在整数溢出吗?只要处理“a”为负值的情况即可(或者更好的方法是,验证您的输入,这样它就不会在第一时间变为负数),您应该很好:)a
溢出。a*2==0
当a==1我加上cout,这是产生错误的最小示例吗?经过288次迭代后,这正好等于…导致这一情况的x的违规值是什么?它只发生在x的一个值上吗?你知道,你只是在循环中,不断增加修正指数,最终达到288。这可能会发生得很快,因为现在循环速度很快(不再有巴贝奇时代用仓鼠来旋转齿轮的机械计算器了)。除此之外,几乎没有什么事情会突然发生。如果这是一个可重复的错误,那么你每次都在错误地做同样的事情。你需要记录或观察发生了什么,看看代码在哪里崩溃。@madmik3这正是我刚才对他说的:)需要更多信息。基本上我想说的是,是x=0x80800000当这种情况发生时,我现在试图在visual studio中测试它,我之前使用的是gdb,使用的是unix,老师为我们提供了一个测试用例程序。我相信我们使用的是gcc,我们“制造”它在unix中运行,然后在它上面执行一个测试客户机。测试客户机告诉我是否出错。它声称在测试0x80800000上它出错了,我已经把它缩小到无法前进,因为a被设置为0,而exponent被设置为288出于某种上帝预见的原因考虑查看gdb来逐步完成代码。你只需要回答一下红色你自己的问题:)“0x80800000”设置了符号位。当“a”变为负数时会发生什么?你一直乘以2?哎呀;)奇怪的格式对类是必要的,什么都没有。我不能直接使常量大于8位,也不能使用"一直在研究它,可能是它溢出了A值,似乎我必须为这种情况设置一个检查条件。不能使常数大于8位???我希望你忘记这个类教给你的东西-这段代码中有很多可怕的做法,这使得它很难验证,而且速度不比可维护的替换代码快ive。@oorosco:是的,a
溢出,需要未签名
。这里有一个可行的解决方案。@oorosco:永远不要忘记你的老师是一个可怜的程序员,他需要断言他的8位方法是相关的
fraction = (~(((0x01)<< 31) >> 8)) & (x << (24 - (exponent + 1)));