John Boyd John Boyd - 10 months ago 48
C Question

Can I use memcmp to check struct for non-zero members?

I am using a large struct with many members, and I would like an easy way to quickly see if any of the members are non-zero. I know that

should not be used to compare two structs for equality (as explained here: How do you compare structs for equality in C?), but I am hoping that by comparing a struct to a block of memory that has been set to 0, this may work.

For example, assume I have some struct:

typedef struct {
int Int1;
int Int2;
int Int3;
} MyInts;

I create a variable from this struct:

MyInts MyStruct = {0};

Throughout execution of my program, the members of
will usually be 0, but may occasionally be set to some non-zero value temporarily. I want to quickly check if any of the ints in
are non-zero. Can I use
as below?

// 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));

Answer Source

You can't do this in the general case, because structs can have padding between fields and at the end of the struct, and the contents of the pad bytes isn't guaranteed (could be uninitialized garbage).

If both structs being compared were initially allocated with calloc, or had sizeof(thestruct) bytes memset to zero before filling in the real values though, then the padding would have predictable values, and memcmp would work. Similarly, if you can guarantee no padding, then this memcmp would work. But if one of them might not have been zeroed, nope, not safe.

Of course, if you want to be "nice", you could just compare the members directly, possibly in a factored out function, and let the compiler handle optimizing, without worrying if you have unzeroed structs with padding floating around.

Note: The second highest voted answer at the link you provided covers this. The comments on that answer also note some edge cases, e.g. floats can have values that compare equal but have different bit representations, so it's not generalizable to all structs even so.