C Language Programming for Beginners: How to Determine Equality of Structs

Source fromtypedef

The Importance of Structs in Programming

Today, let’s talk about structs in C language. They are like building blocks, allowing you to combine various data types into a meaningful “little group”. If you haven’t grasped structs yet, be sure to check out my previous article! Detailed Explanation of C Language Structs (struct)

When it comes to comparing two structs, we commonly use two methods: comparing each member one by one, or using <span>memcmp</span> for a thorough sweep. Next, let’s take a closer look at how these two methods are implemented and their minor issues.

Member-by-Member Comparison

The member-by-member comparison is simple and effective. For example, consider a struct that contains int, float, and pointer types of data; let’s see how to compare them one by one:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>

typedef struct {
  int a;
  float b;
  char *d;
} MyStruct;

#define EPSILON 0.000001

bool FloatsIsEqual(float f1, float f2) {
  return fabs(f1 - f2) < EPSILON;
}

bool compareStructs(MyStruct s1, MyStruct s2) {
  if (s1.a != s2.a) return false;
  if (!FloatsIsEqual(s1.b, s2.b)) return false;
  if (strcmp(s1.d, s2.d) != 0) return false;
  return true;
}

int main() {
  MyStruct s1 = {520, 2.5f, "typedef"};
  MyStruct s2 = {520, 2.5f, "typedef"};

  if (compareStructs(s1, s2)) {
    printf("Structures are equal");
  } else {
    printf("Structures are not equal");
  }
  return 0;
}

Using memcmp for Comparison

<span>memcmp</span> is a C library function used to compare the first n bytes of two memory blocks. Its function prototype is as follows:

int memcmp(const void *str1, const void *str2, size_t n)
  • Parameters
    • str1 — Pointer to the first memory block.
    • str2 — Pointer to the second memory block.
    • n — Number of bytes to compare.
  • Return Value
    • If the return value < 0, it indicates str1 is less than str2.
    • If the return value > 0, it indicates str1 is greater than str2.
    • If the return value = 0, it indicates str1 is equal to str2.

However, caution is needed when using <span>memcmp</span>:

  • Struct Alignment: Due to potential memory alignment in structs, some bytes may be padded, which could lead to incorrect results when using <span>memcmp</span> directly.
  • Floating Point Comparison: The storage format of floating-point numbers is special, and using <span>memcmp</span> for comparison may yield inaccurate results.

Negative Example

Here is a personal experience of a <span>Bug</span> I encountered. There was a piece of code that compared two structs for equality using the member-by-member method, and then I thought I would be clever and switched to using <span>memcmp</span>, which unsurprisingly led to unexpected results.

Below is an example demonstrating the use of <span>memcmp</span> to compare two struct variables containing positive zero and negative zero:

#include <stdio.h>
#include <string.h>

typedef struct {
  float value;
} FloatStruct;

int main() {
  FloatStruct s1 = {0.0f}; // Positive zero
  FloatStruct s2 = {-0.0f}; // Negative zero

  if (memcmp(&s1, &s2, sizeof(FloatStruct)) == 0) {
    printf("Structures are equal");
  } else {
    printf("Structures are not equal");
  }
  return 0;
}

Although the two struct members are numerically equal, both being 0, their <span>sign bits</span> differ in storage format, resulting in different data stored in memory, thus leading to the conclusion that the two structs are not equal, contrary to our expectations.

Conclusion

If a struct contains floating-point or pointer types, we should use the member-by-member comparison method, which is simple and effective. For simple integer data, using <span>memcmp</span> can be a shortcut.

For the sake of program extensibility, it is still recommended to use the member-by-member comparison.

END

C Language Programming for Beginners: How to Determine Equality of Structs

Leave a Comment