theWizard
theWizard

Reputation: 111

why memcmp returns -1 although equal

I'm comparing using memcmp() two variables of the same struct (the struct has union in it). The variables are in two arrays and I'm running a loop where each iteration I do memcmp(&arr1[i], &arr2[i], sizeof(arrtype)).

When debugging I see that memcmp returns -1, but looking at the two variables and their values, I see that the variables has equal values. These arrays are zeroed with memset at the beginning.

  1. So does anybody know why memcmp returns -1 and not 0?
  2. Is there a better way to do what I need (compare two memory blocks)?

code:

typedef struct type1 {
    int version;
    union {
            option1_t opt1;
            option2_t opt2;
    } union_t;
} type1_t;

typedef struct type0 {
    type1_t member1;
    type2_t member2;
    type3_t member3;
    type4_t member4;
    type5_t member;
} type0_t;


type0_t arr1[SIZE];
type0_t arr2[SIZE];

memset(arr1, 0, SIZE * sizeof(type0_t));
memset(arr2, 0, SIZE * sizeof(type0_t));

/* doing irrelevant stuff... */

/* get values into arr1, arr2 ... */


/* comparing both arrays in for loop*/
value = memcmp(&arr1[i], &arr2[i], sizeof(type0_t));

Upvotes: 2

Views: 3804

Answers (3)

sehe
sehe

Reputation: 393809

You are likely reading indeterminate values (unitialized memory, or memory overwritten to contain unspecified data).

E.g. you could be accessing a member of a union that wasn't the member last written. Even if you don't, the last-written member might be smaller than the total extents of the union, leading to 'indeterminate' data beyond that size.

struct X { 
    union {
         char field1;
         long long field2[10];
    };
};

struct X a,b;
a.field1 = 'a';
b.field1 = 'a';

You can't expect a and b to compare equal bitwise because you never initialized all the bits in the first place (field2 has many more bits in excess of field1)

---Depending on the value of uninitialized memory also invokes Undefined Behaviour.--- Not true for C11

Upvotes: 9

Eric Postpischil
Eric Postpischil

Reputation: 224310

Using memcmp to compare two objects may fail for three reasons:

  1. A struct may contain padding bytes whose values are not controlled.
  2. A union may contain bytes that do not correspond to bytes of the last-stored member (e.g., the additional bytes for one of the longer members of the union).
  3. Types may have equal values with different representations (padding bits within the type, different encodings for +0 and –0, et cetera).

Unless you have taken steps to ensure that none of these problems interferes with comparing via memcmp, then the proper way to compare two structures is to compare them member-by-member.

Upvotes: 2

Devolus
Devolus

Reputation: 22094

If you are using structures, there can be padding bytes in between your member fields. You might try to memeset the whole structure to 0 before you start using it.

Upvotes: 4

Related Questions