1. There are similar functions (like std::lexicographical_compare() in C++) returning bool instead an int.
2. It's not crazy to read memcmp() as comparing for equality rather than ordering. i.e. I think when you see 'if (memcmp(a, b, n))', it's quite natural for one's brain to read it as "if a and b are equal..."
For someone who uses memcmp() on a daily basis, you probably don't encounter these misconceptions. But as someone who writes C++ and merely deals with C once in a while in the process, both of these possibilities have tripped me up multiple times when seeing if (memcmp(...)). Writing != 0 has always cleared that confusion for me, since it immediately signals the result (a) isn't meant to be read as a Boolean, and (b) might be negative, thus putting my brain on alert.
int memeq( const void* lhs, const void* rhs, size_t count ) {
return memcmp( lhs, rhs, count ) == 0;
}
One could have an analogous memneq() with != 0, but I preferred to just use the ! operator on the memeq() result.I would also use a typedef for the struct, so you don't have to keep writing "struct" everywhere:
typedef struct {
int x, y, z;
} tmp;
With those two tricks and more generous whitespace for clarity, the erroneous memcmp() call becomes: if( ! memeq( m_result_original, m_result_my_version, sizeof(tmp) ) )
You're a lot less likely to get that wrong.That said, this code, even with my updates, was wrong all along. Using memcmp() on two structs, even with a wrapper, is a bad idea. What if there is padding?!
This particular struct will not have padding, but in the more general case you shouldn't count on that.
What you really need to do is have a function that explicitly compares the x, y, and z fields of these two structs.
Then you won't have to worry about uninitialized padding, you will never get the length wrong, and everything will always just work.
Comparing it to false requires me to know that false is 0. Comparing it to a ptr requires me to know that 0 represents a pointer pointing to nothing.
C does not have a boolean type. (The `true` and `false` defined in stdbool.h are macros expanding to the integer literals 1 and 0, respectively.)
Functions which return 0 on success I always compare with 0 as “if (foo()) error();” easily gets confusing. If I see “if (foo() != 0) error();” then I can easily tell what’s going on because C is funny like that.
Conversely, if I’m testing for truthfulness or NULL I’ll use the boolean operators.
if (!((my_ptr = malloc (sizeof (struct my_struct))) != NULL))
exit (1);Also, put the constant value (0 or true or null) on the left side.