在一个 C/C++ 混合项目中,我发现了一些我可以简化为的代码
#include <mem.h>
struct StructContainingDouble
{
double d;
/// other elements omitted
};
void clear(StructContainingDouble* p)
{
memset(p, 0, sizeof *p);
}
不停止 Cppcheck 以引发可移植性警告
Using memset() on struct which contains a floating point number.
消息是正确的,但是由于 float 被声明为 double ,所以它似乎是误报,因为在 double 中,(正)零值是按照 IEEE 754 标准编码的:[*]
0 00000000000 0000000000000000000000000000000000000000000000000000
所以我倾向于简单地抑制警告并忘记它
void clear(ContainingDouble* p)
{
// cppcheck-suppress memsetClassFloat
memset(p, 0, sizeof *p);
}
但也许这里真的存在可移植性问题?
附录:
实际代码基于Win32平台。该结构用于管理对 shared memory 的访问,这就是构造函数无用的原因。不仅该结构的一个对象必须归零,而且它的一个数组嵌入到另一个结构中,如下所示:
#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);
}
最佳答案
有问题吗?是的。不,不是真的。一个非常遥远的也许。
正如 interjay 在评论中指出的那样,C 不强制要求浮点值的格式。因此理论上“零”可能是无效值或不代表零。
所有具有 FPU 的现代平台都实现 IEEE 754。任何(可能是嵌入式)系统都不会在其库中实现 IEEE 754(除非它是退化的实现并且根本没有浮点...)。
因此,虽然不能保证您在这里遇到问题的可能性很小。
在一些平台上存在关于它们如何精确地符合 IEEE 754 信件的细节问题,但之前曾问过但从未得到任何答案我会很高兴看到一个平台,其中 memset()
带零的 double 不会将其设置为零值。
就是说,如果您开始将 double up 切碎但使用 0 则不要忘记字节序,这不是问题。
请记住 C 已经接近 50 岁了,现在几乎普遍存在的东西,例如一个字节是 8 位,还没有确定下来,我认为这是正确的,为了提供最大的支持(不要忘记嵌入式)它是从未 promise 遵守这些标准。
在偏执狂模式下你可以:
memset(&obj,0,sizeof obj);
#ifndef __STDC_IEC_559__
obj.dbl_val=0.0;
#endif
其中 dbl_val
是 obj
的 double
成员。然而,未定义的唯一可能原因不是因为 block 归零不是零,而是标准的其他一些优点没有完全实现。
关于c++ - 在包含 float 的结构上使用 memset(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45481484/