问题
Is the defacto method for comparing arrays (in C) to use memcmp
from string.h
?
I want to compare arrays of ints and doubles in my unit tests
I am unsure whether to use something like:
double a[] = {1.0, 2.0, 3.0};
double b[] = {1.0, 2.0, 3.0};
size_t n = 3;
if (! memcmp(a, b, n * sizeof(double)))
/* arrays equal */
or to write a bespoke is_array_equal(a, b, n)
type function?
回答1:
memcmp
would do an exact comparison, which is seldom a good idea for floats, and would not follow the rule that NaN != NaN. For sorting, that's fine, but for other purposes, you might to do an approximate comparison such as:
bool dbl_array_eq(double const *x, double const *y, size_t n, double eps)
{
for (size_t i=0; i<n; i++)
if (fabs(x[i] - y[i]) > eps)
return false;
return true;
}
回答2:
Replace memset
with memcmp
in your code, and it works.
In your case (as the size both arrays arrays are identical and known during compilation) you can even do:
memcmp(a, b, sizeof(a));
回答3:
Using memcmp
is not generally a good idea. Let's start with the more complex and work down from there.
Though you mentioned int
and double
, I first want to concentrate on memcmp
as a general solution, such as to compare arrays of type:
struct {
char c;
// 1
int i;
// 2
}
The main problem there is that implementations are free to add padding to structures at locations 1 and 2, making a bytewise comparison potentially false even though the important bits match perfectly.
Now down to doubles. You might think this was better as there's no padding there. However there are other problems.
The first is the treatment of NaN
values. IEEE754 goes out of its way to ensure that NaN
is not equal to any other value, including itself. For example, the code:
#include <stdio.h>
#include <string.h>
int main (void) {
double d1 = 0.0 / 0.0, d2 = d1;
if (d1 == d2)
puts ("Okay");
else
puts ("Bad");
if (memcmp (&d1, &d2, sizeof(double)) == 0)
puts ("Okay");
else puts
("Bad");
return 0;
}
will output
Bad
Okay
illustrating the difference.
The second is the treatment of plus and minus zero. These should be considered equal for the purposes of comparison but, as the bit patterns are different, memcmp
will say they are different.
Changing the declaration/initialisation of d1
and d2
in the above code to:
double d1 = 0.0, d2 = -d1;
will make this clear.
So, if structures and doubles are problematic, surely integers are okay. After all, they're always two's complement, yes?
No, actually they're not. ISO mandates one of three encoding schemes for signed integers and the other two (ones' complements and sign/magnitude) suffer from a similar problem as doubles, that fact that both plus and minus zero exist.
So, while they should possibly be considered equal, again the bit patterns are different.
Even for unsigned integers, you have a problem (it's also a problem for signed values as well). ISO states that these representations can have value bits and padding bits, and that the values of the padding bits are unspecified.
So, even for what may seem the simplest case, memcmp
can be a bad idea.
回答4:
The function you're looking for is memcmp
, not memset
. See the answers to this question for why it might not be a good idea to memcmp
an array of doubles though.
回答5:
memcmp compares two blocks of memory for number of size given
memset is used to initialise buffer with a value for size given
buffers can be compared without using memcmp in following way. same can be changed for different datatypes.
int8_t array_1[] = { 1, 2, 3, 4 }
int8_t array_2[] = { 1, 2, 3, 4 }
uint8_t i;
uint8_t compare_result = 1;
for (i = 0; i < (sizeof(array_1)/sizeof(int8_t); i++)
{
if (array_1[i] != array_2[i])
{
compare_result = 0;
break;
}
}
来源:https://stackoverflow.com/questions/8399928/c-array-comparison