Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 非法浮点值_C_Exception_Gcc - Fatal编程技术网

C 非法浮点值

C 非法浮点值,c,exception,gcc,C,Exception,Gcc,我目前正在开发一个嵌入式微控制器,并使用一个定制的printf例程。该工具链是AVR32体系结构的GCC工具链 我的问题是,在第二次调用vsnprintf或类似命令时,CPU会进入异常状态 我从支持部门得到的答复是: 我们找不到这种行为的任何明显原因。但是,通过逐字节写入来创建浮点溢出条件是不安全的。我们无法确保由此产生的值,建议使用“FLT_MAX”进行检查 现在我想知道:什么是“非法”浮点值?难道所有的位组合不应该至少代表某个值吗?如果相关:sizeof(float)是4个字节 我没有研究A

我目前正在开发一个嵌入式微控制器,并使用一个定制的printf例程。该工具链是AVR32体系结构的GCC工具链

我的问题是,在第二次调用vsnprintf或类似命令时,CPU会进入异常状态

我从支持部门得到的答复是:

我们找不到这种行为的任何明显原因。但是,通过逐字节写入来创建浮点溢出条件是不安全的。我们无法确保由此产生的值,建议使用“FLT_MAX”进行检查


现在我想知道:什么是“非法”浮点值?难道所有的位组合不应该至少代表某个值吗?如果相关:sizeof(float)是4个字节

我没有研究AVR32,但是“非法”浮点值,通常浮点(单精度算术)是数值方法中的重要主题。浮点数的最大值为:

FLT_MAX = 3.40282e+38
但float也有对浮点值的限制。越接近零,可以指定的浮点数就越多

例如:

[1,2]之间的最小值是
1.19209e-07
(它是2^-23),也称为macheps(机器ε(float.h中的FLT_ε))

[2,4]之间的最小值为
2*1.19209e-07
=
2*2^-23
它也适用于订单端: [1/2,1]之间的最小值为
2^-24

为什么会这样? 让我们将数字定义为
beforedot.afterdot

数字越大,在点number之前写入
所需的位数就越多,而simmetric表示的位数就越少

总之:

浮动的最小值:
1.0842e-19

浮动最大值:
3.40282e+38

汇总 我建议您打印浮点值的位,就像它们是十六进制整数一样,如下面的代码所示,这样您就可以分析这些位,看看它们是否包含您试图计算的值,或者是否由于某些错误而被不正确地修改

细节 “浮点硬件符合基于IEEE 754浮点标准的C标准的要求。”后一条款是错误的;C标准不是基于IEEE 754。C标准确实规定了与IEEE 754的绑定(通过名称IEC 60559)作为C实现的可选功能,我将假定您使用的AVR32 CPU模型在某种程度上符合IEEE 754

IEEE 754中没有“非法”值。有些值不代表数字,其中一些值旨在引起异常。这种值称为NaN(表示“非数字”)。有静默NaN和信令NaN。静默NaN旨在以静默方式通过操作,产生NaN结果。例如,
3+NaN
应产生
NaN
。信令NaN旨在导致异常,这可能导致程序控制的更改(例如信号或程序中止)

上面引用的技术参考手册还说“不提供信号NaN,所有NaN均为非信号(安静)。”

一个好的
vsnprintf
例程应该接受安静的NaN值进行打印,并且应该通过生成诸如“NaN”之类的字符串对它们进行格式化。当传递一个信号NaN进行格式化时,我想格式化它或生成一个异常可能是合理的

我想您从支持部门收到的信息是,您的软件创建了某种NaN,而
vsnprintf
无法处理这些问题。从措辞上看,我认为他们的反应是推测性的

如果您是通过汇编字节来创建浮点值,那么如果软件中出现错误,您可能在无意中创建了NaN。我建议您通过使用
vsnprintf
打印浮点值的字节来调试此操作,而不是使用浮点格式说明符打印它

如果您使用的GCC版本具有GCC的常见功能,并且实现中的
无符号int
为32位,则可以使用以下方法将32位
浮点值
x
的位格式化为十六进制值:

vsnprintf(Buffer, BufferLength, "0x%x",
    (union { float f; unsigned int u; }) {x} .u);
第二行使用复合文字将值
x
放入并集,并将其字节重新解释为
无符号int
。(这在C中是一种受支持的重新解释对象字节的方法。许多人使用指针别名,如果使用适当的标志,这在GCC中是有效的,但C标准通常不支持。另一种受支持的方法是复制字节,如
unsigned int u;memcpy(&u,&x,sizeof u);

一旦您看到
浮点
中的位是什么,您可以从IEEE 754标准中的信息或使用手动解释它们。(选择“十六进制”按钮以输入要解释的十六进制值。)

在IEEE-754 32位二进制浮点对象中,如果:

  • 位31具有任何值。(它是符号位,与识别NaN无关。)
  • 位30到23都是1
  • 位22到0并不都是零

(如果第30位到第23位都是1,但第22位到第0位都是0,则该值为无穷大。这不是非法的,但也可能导致低质量的
vsnprintf
生成异常。)

嗯,应该是这样,但可能他们的观点是“通过逐字节写入来创建浮点溢出条件”,而不仅仅是“创建浮点溢出”。您的错误代码是什么?您是否捕获到浮点异常?您应该了解引发的异常类型,因为FPU可能会导致某些异常(取决于值),尤其是在微控制器环境中,您可能需要自己处理这些异常(取决于您的环境).AVR32不支持浮点异常。得到浮点异常的唯一明显原因是printf()代码失效。这取决于该代码的程序员