我可以使用 memcmp 检查结构中的非零成员吗?
Can I use memcmp to check struct for non-zero members?
我正在使用一个包含许多成员的大型结构,我想要一种简单的方法来快速查看是否有任何成员非零。我知道 memcmp()
不应该用于比较两个结构是否相等(如此处解释:How do you compare structs for equality in C?),但我希望通过将结构与已设置为 0 的内存块进行比较,这可能有效。
例如,假设我有一些结构:
typedef struct {
int Int1;
int Int2;
int Int3;
} MyInts;
我从这个结构创建了一个变量:
MyInts MyStruct = {0};
在我的程序的整个执行过程中,MyStruct
的成员通常为 0,但有时可能会临时设置为一些非零值。我想快速检查 MyStruct
中的任何整数是否非零。我可以像下面那样使用 memcmp()
吗?
// Create empty struct to test against
MyInts EmptyStruct = {0};
// Make sure entire memory block of test struct is cleared
memset(&EmptyStruct, 0, sizeof(MyInts));
// Compare MyStruct to EmptyStruct to see if any non-zero members exist
int result = memcmp(&MyStruct, &EmptyStruct, sizeof(MyInts));
在一般情况下您不能这样做,因为结构可以在字段之间和结构的末尾进行填充,并且不能保证填充字节的内容(可能是未初始化的垃圾)。
如果两个被比较的结构最初分配了calloc
,或者sizeof(thestruct)
字节memset
在填充实际之前为零值,那么填充将具有可预测的值,并且 memcmp
将起作用。同样,如果你能保证没有填充,那么这个 memcmp
就可以了。但是,如果其中之一可能没有被归零,不,不安全。
当然,如果你想成为 "nice",你可以直接比较成员,可能在分解函数中,让编译器处理优化,而不用担心你是否有带填充的未清零结构飘来飘去。
注意:您提供的 link 中的 The second highest voted answer 涵盖了这一点。对该答案的评论还指出了一些边缘情况,例如float
s 可以具有比较相等但具有不同位表示的值,因此即使如此它也不能推广到所有结构。
为了清楚起见,我决定继续并根据评论回答我自己的问题。正如@M.M 提到的,填充不能保证被结构赋值保留,也可能不会被单个成员赋值保留。因此,使用 memcmp
检查非零成员的结构是不安全的。
如 那样,安全的做法是单独比较每个结构成员。
我正在使用一个包含许多成员的大型结构,我想要一种简单的方法来快速查看是否有任何成员非零。我知道 memcmp()
不应该用于比较两个结构是否相等(如此处解释:How do you compare structs for equality in C?),但我希望通过将结构与已设置为 0 的内存块进行比较,这可能有效。
例如,假设我有一些结构:
typedef struct {
int Int1;
int Int2;
int Int3;
} MyInts;
我从这个结构创建了一个变量:
MyInts MyStruct = {0};
在我的程序的整个执行过程中,MyStruct
的成员通常为 0,但有时可能会临时设置为一些非零值。我想快速检查 MyStruct
中的任何整数是否非零。我可以像下面那样使用 memcmp()
吗?
// Create empty struct to test against
MyInts EmptyStruct = {0};
// Make sure entire memory block of test struct is cleared
memset(&EmptyStruct, 0, sizeof(MyInts));
// Compare MyStruct to EmptyStruct to see if any non-zero members exist
int result = memcmp(&MyStruct, &EmptyStruct, sizeof(MyInts));
在一般情况下您不能这样做,因为结构可以在字段之间和结构的末尾进行填充,并且不能保证填充字节的内容(可能是未初始化的垃圾)。
如果两个被比较的结构最初分配了calloc
,或者sizeof(thestruct)
字节memset
在填充实际之前为零值,那么填充将具有可预测的值,并且 memcmp
将起作用。同样,如果你能保证没有填充,那么这个 memcmp
就可以了。但是,如果其中之一可能没有被归零,不,不安全。
当然,如果你想成为 "nice",你可以直接比较成员,可能在分解函数中,让编译器处理优化,而不用担心你是否有带填充的未清零结构飘来飘去。
注意:您提供的 link 中的 The second highest voted answer 涵盖了这一点。对该答案的评论还指出了一些边缘情况,例如float
s 可以具有比较相等但具有不同位表示的值,因此即使如此它也不能推广到所有结构。
为了清楚起见,我决定继续并根据评论回答我自己的问题。正如@M.M 提到的,填充不能保证被结构赋值保留,也可能不会被单个成员赋值保留。因此,使用 memcmp
检查非零成员的结构是不安全的。
如