Wol*_*olf 4 c c++ double portability cppcheck
在C/C++混合项目中,我发现了一些我可以减少的代码
#include <mem.h>
struct StructContainingDouble
{
double d;
/// other elements omitted
};
void clear(StructContainingDouble* p)
{
memset(p, 0, sizeof *p);
}
Run Code Online (Sandbox Code Playgroud)
不停止Cppcheck提高可移植性警告
在包含浮点数的struct上使用memset().
消息是正确的,但由于浮点数被声明为double,因此它似乎是误报,因为在(正)零值的两倍中,按照IEEE 754标准进行编码:[*]
0 00000000000 0000000000000000000000000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)
因此,我倾向于简单地压制警告而忘记它
void clear(ContainingDouble* p)
{
// cppcheck-suppress memsetClassFloat
memset(p, 0, sizeof *p);
}
Run Code Online (Sandbox Code Playgroud)
但也许这里真的存在可移植性问题?
实际代码基于Win32平台.该结构用于管理对共享内存的访问,这就是构造函数无用的原因.而且不仅是该结构的一个对象必须归零,而是嵌入另一个结构的数组,如下所示:
#include <mem.h>
struct Slot
{
double d;
// more members...
};
struct SharedMem
{
Slot slots[2048];
// more members...
};
void clear(SharedMem* p)
{
memset(p, 0, sizeof *p);
}
Run Code Online (Sandbox Code Playgroud)
[*] from:双精度浮点格式 - 维基百科
这是个问题吗?是.不,不是真的.一个非常遥远的人.
正如interjay C的评论中指出的那样,C并没有规定浮点值的格式.因此理论上"零"可能是无效值或不代表零.
如果他们有FPU,所有现代平台都实现IEEE 754.任何(可能是嵌入式的)系统都不会在其库中实现IEEE 754(除非它是简并实现,并且根本没有浮点...).
因此,虽然无法保证您在这里遇到问题的可能性很小.在某些平台上存在一些问题,关于它们如何精确地符合IEEE 754的字母,但之前已经问过并且从未得到任何答案,我会很高兴这里有memset()一个双零的平台没有设置它零的价值.
也就是说,如果你开始斩首加倍但不要忘记字数,那就不是问题.
记得C已经接近50岁了,现在几乎是通用的东西,如一个字节是8位还没有安定下来,我认为非常正确,为了提供最大的支持(不要忘记嵌入式)它永远不会致力于这些标准.
在偏执狂模式中你可以选择:
memset(&obj,0,sizeof obj);
#ifndef __STDC_IEC_559__
obj.dbl_val=0.0;
#endif
Run Code Online (Sandbox Code Playgroud)
哪里dbl_val是double的成员obj.然而,唯一可能的原因是未定义不是因为块归零不是零,而是标准的其他一些细节没有完全实现.
我认为在这种特殊情况下,可移植性考虑因素已经太过分了.我没有看到我的生活(我编程30多年)任何硬件或C实现,其中零意味着零以外的东西.当然可以创建任何数字格式,其中零不为零(例如,带有由ASCII数字代码表示的数字的BDC - 但这不是这里的情况),但我们讨论真实的现有硬件和软件.
所以IMO memset为零是安全和可移植的,即使标准说浮点数是实现定义的,因为我不知道任何现有的实现,其中零意味着不是零,这样的实现将是非常不切实际的.
前面已经提到,C 不保证任何特定的浮点实现。
嗯,C++ 也没有。不需要浮点值的特定实现。
[基础.基础]
浮点类型共有三种:float、double 和 long double。[...] 浮点类型的值表示是实现定义的。
因此,memset无论是在 C 还是 C++ 中,浮点值都是不可移植的。