【发布时间】:2019-04-20 20:51:07
【问题描述】:
我有一个定义如下的结构:
struct s_zoneData {
bool finep = true;
double pzone_tcp = 1.0;
double pzone_ori = 1.0;
double pzone_eax = 1.0;
double zone_ori = 0.1;
double zone_leax = 1.0;
double zone_reax = 0.1;
};
我创建了一个比较运算符:
bool operator==(struct s_zoneData i, struct s_zoneData j) {
return (memcmp(&i, &j, sizeof(struct s_zoneData)) == 0);
}
大多数情况下,比较失败,即使是相同的变量。我花了一些时间(并且弄乱了 gdb)才意识到问题在于 finep 结构元素的填充字节是未初始化的垃圾。作为参考,在我的机器 (x64) 中,sizeof(struct s_zoneData) 是 56,这意味着 finep 元素有 7 个填充字节。
起初,我解决了将 memcmp 替换为结构每个成员的基于 ULP 的浮点值比较的问题,因为我认为可能存在舍入问题。但现在我想更深入地研究这个问题,看看可能的替代解决方案。
问题是,有没有办法为不同的编译器和平台指定填充字节的值?或者,将其重写为更一般的问题,因为我可能过于专注于我的方法,比较两个 struct s_zoneData 变量的正确方法是什么?
我知道创建一个虚拟变量(例如char pad[7])并用零初始化它应该可以解决问题(至少对于我的特定情况),但我读过多种情况,人们在不同的编译器和会员顺序,所以我更愿意使用标准定义的解决方案,如果存在的话。或者至少,保证对不同平台和编译器的兼容性。
【问题讨论】:
-
那其实不太好。不仅因为填充(只能通过使用例如
memset“清除”),还因为它是比较浮点值的一种非常糟糕的方法。事实上,您甚至不应该使用==来比较浮点值,因为两个看似相等的值实际上可能不(由于计算中的复合舍入误差)。要比较浮点值,请检查值之间的差异是否小于特定的 epsilon。 -
这就是为什么我用基于 ULP 的浮点比较替换了
memcmp,对于这种特殊情况。问题与填充字节有关,特别是如何避免使用memcmp比较两个相同的结构时失败,或者比较它们的最佳方法是什么。