tags:

views:

6084

answers:

7

How do you compare two instances of structs for equality in standard C?

+18  A: 

C provides no language facilities to do this - you have to do it yourself and compare each structure member by member.

Greg Hewgill
+5  A: 

If you do it a lot I would suggest writing a function that compares the two structures. That way, if you ever change the structure you only need to change the compare in one place.

As for how to do it.... You need to compare every element individually

Ben
+13  A: 

You may be tempted to use memcmp(&a, &b, sizeof(struct foo), but it may not work in all situations. The compiler may add alignment buffer space to a structure, the contents of this alignment buffer is not guaranteed to be any constant value.

But, if you use calloc or memset the full size of the structures before using them, you can do a shallow comparison with memcmp (if your structure contains pointers, it will match only if the address the pointers are pointing at are the same).

Sufian
Close, because it works on "almost all" compilers, but not quite. Check out 6.2.1.6.4 in C90: "Two values (other than NaNs) with the same object representation compare equal, but values that compareequal may have different object representations."
Steve Jessop
+3  A: 

You can't use memcmp to compare structs for equality due to potential random padding characters between field in structs.

  // bad
  memcmp(&struct1, &struct2, sizeof(struct1));

The above would fail for a struct like this:

typedef struct Foo {
  char a;
  /* padding */
  double d;
  /* padding */
  char e;
  /* padding */
  int f;
} Foo ;

You have to use member-wise comparison to be safe.

Unlikely to be padding after the double; the char will be perfectly adequately aligned immediately after the double.
Jonathan Leffler
A: 

If the structs only contain primitives or if you are interested in strict equality then you can do something like this:

int my_struct_cmp(const struct my_struct * lhs, const struct my_struct * rhs)
{
    return memcmp(lhs, rsh, sizeof(struct my_struct));
}

However, if your structs contain pointers to other structs or unions then you will need to write a function that compares the primitives properly and make comparison calls against the other structures as appropriate.

Be aware, however, that you should have used memset(&a, sizeof(struct my_struct), 1) to zero out the memory range of the structures as part of your ADT initialization.

Kevin S.
A: 

Note you can use memcmp() on non static stuctures without worrying about padding, as long as you don't initialise all members (at once). This is defined by C90:

http://www.pixelbeat.org/programming/gcc/auto_init.html

pixelbeat
+1  A: 

It depends on whether the question you are asking is:

  1. Are these two structs the same object?
  2. Do they have the same value?

To find out if they are the same object, compare pointers to the two structs for equality. If you want to find out in general if they have the same value you have to do a deep comparison. This involves comparing all the members. If the members are pointers to other structs you need to recurse into those structs too.

In the special case where the structs do not contain pointers you can do a memcmp to perform a bitwise comparison of the data contained in each without having to know what the data means.

Make sure you know what 'equals' means for each member - it is obvious for ints but more subtle when it comes to floating-point values or user-defined types.

domgblackwell