在包含浮点数的结构上使用 memset()
Using memset() on struct which contains a floating point number
在 C/C++ 混合项目中,我找到了一些可以简化为
#include <mem.h>
struct StructContainingDouble
{
double d;
/// other elements omitted
};
void clear(StructContainingDouble* p)
{
memset(p, 0, sizeof *p);
}
无需停止 Cppcheck 以引发可移植性警告
在包含浮点数的结构上使用 memset((。
该消息是正确的,但由于浮点数被声明为双精度,因此它似乎是误报,因为在双精度中,(正(零值是按照 IEEE 754 标准编码的:[*]
0 00000000000 0000000000000000000000000000000000000000000000000000
所以我倾向于简单地抑制警告并忘记它
void clear(ContainingDouble* p)
{
// cppcheck-suppress memsetClassFloat
memset(p, 0, sizeof *p);
}
但也许这里真的存在可移植性问题?
补遗:
实际代码基于 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);
}
[*]来自: 双精度浮点格式 - 维基百科
有问题吗?是的。不,不是真的。也许非常遥远。
正如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
其中dbl_val
是obj
的double
成员。然而,未定义的唯一可能原因不是因为块归零不为零,而是标准的其他一些细节没有完全实现。
我认为在这种特殊情况下,可移植性考虑已经走得太远了。我一生中(我做编程30 +年(没有见过任何硬件或C实现,其中零意味着零以外的其他东西。当然,可以创建零不为零的任何数字格式(例如BDC与ASCII数字代码表示的数字 - 但这里不是这种情况(,但我们讨论的是实际存在的硬件和软件。
因此,即使标准说浮点数是实现定义的,IMO 内存设置为零也是安全且可移植的,因为我不知道任何现有的实现,其中零意味着零以外的其他东西,并且这样的实现将极其不切实际。
前面已经提到,C 不保证任何特定的浮点实现。
好吧,C++也没有。不需要浮点值的特定实现。
[基础.基础]
有三种浮点类型:浮点型、双精度型和长型双精度型。 [...]浮点类型的值表示形式为 实现定义。
因此,memset
浮点值在 C 或 C++ 中都是不可移植的。
实际代码用于初始化Windows(Win32(下的共享内存。这意味着代码很可能会被移植(如果有的话(到具有适当IEEE 754支持的某个平台。
这就是为什么我建议将不可移植性结合起来:
-
使用
WinBase.h
中定义的ZeroMemory
宏(通过Windows.h
(明确声明您没有尝试将一些花哨的位模式存储到浮点数据中。 -
在该调用之前禁用 Cppcheck 的可移植性警告。
换句话说:
#include <windows.h>
// ...
void clear(SharedMem* p)
{
// cppcheck-suppress memsetClassFloat
ZeroMemory(p, sizeof *p);
}
- sizeof 函数如何在带和不带位字段的结构上工作?(填充)
- 未使用的 asm() 在不受支持的体系结构上的行为
- 复制引用结构上的赋值
- 有了memory_order_relaxed,原子变量的总修改顺序如何在典型体系结构上得到保证
- C 嵌套结构上的 g++ 编译错误
- 结构上溢出的整数加法
- 在通过 P/Invoke 获取的 C++ 结构上设置 C# 回调
- 在包含浮点数的结构上使用 memset()
- 在模板化数据结构上调用 begin() 或 end()
- 在现有数据结构上使用BGL算法需要什么(边和顶点作为矢量<对象*>)?
- boost :: Spirit :: Karma语法:逗号从结构上划定了带有选件属性的输出
- 使用提升库在队列和堆栈数据结构上保存和加载数据时出错
- 所有结构上的奇怪内存位移
- 是在同一体系结构上运行的静态编译的纯标准C 程序可移植
- 在英特尔x86体系结构上使用非AVX指令修改xmm整数寄存器值
- 结构上的内存分配和复制构造函数
- 结构上的 C++ 中的比较器函数
- 用载体建立在苍蝇递归结构上
- 为什么在不同的计算机体系结构上,相同的GCC的编译选项会有所不同
- NUMA体系结构上大(8MB)内存区域的可扩展分配