﻿# V2629\. MISRA\. Pointer arguments to the 'memcmp' function should point to an appropriate type\.

This diagnostic rule is based on the [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) software development guidelines\.

The diagnostic rule is relevant only for C\.

The [`memcmp`](https://en.cppreference.com/w/c/string/byte/memcmp) function from the standard library can lead to unexpected results when used with certain data types\.

The function compares the first `n` bytes of two objects passed via pointers, byte by byte\. However, there are cases when`memcmp` should not be used for byte\-by\-byte comparison\.

**The case N1**\. Structures or unions\. Due to [data alignment](https://pvs-studio.com/en/blog/terms/0011/), logically equal objects may produce different results\.

The example:

```cpp
struct S 
{
  int  a;
  char b;
};

bool equals(struct S *s1, struct S *s2)
{
  return memcmp(s1, s2, sizeof(struct S)) == 0;
}
```

To clarify, assume that the size and alignment of `int` are `4`, while for `char` they are `1`\. Since the processor must process data in memory efficiently, the `S` structure will be arranged in memory as follows:

```cpp
class S size(8):
     +---
 0   | a
 4   | b
     | <alignment member> (size=3)
     +---
```

The first member is located at offset `0x0` and occupies 4 bytes\. The next member is located at offset `0x4` and occupies 1 byte\. In addition, starting from offset `0x5`, 3 bytes are added to the class objects to align them to a maximum alignment of 4 bytes\.

The C language standard does not specify how padding bytes will be initialized\. As a result, comparing two objects using the `memcmp` function may yield incorrect results\.

The correct way to compare two objects is to compare each member of the class pairwise:

```cpp
struct S 
{
  int  a;
  char b;
};

bool equals(struct S *s1, struct S *s2)
{
  return s1->a == s2->a && s1->b == s2->b;
}
```

**The case N2**\. Real numbers\. Look at the example:

```cpp
bool equals(double *lhs, double *rhs, size_t length)
{
  return memcmp(lhs, rhs, length * sizeof(double)) == 0;
}
```

The function compares two arrays of real numbers of size `length`\. Due to the nuances of real number representation, identical values may have different byte representations\. As a result, `memcmp` may return a different result than the developer expects\.

The better way to compare arrays of real numbers is as follows:

```cpp
bool equals_d(double lhs, double rhs, double eps = DBL_EPSILON);

bool equals(double *lhs, double *rhs, size_t length)
{
  for (size_t i = 0; i < length; ++i)
  {
    if (!equals_d(lhs[i], rhs[i])) return false;
  }

  return true;
}
```

The comparison function for two real numbers is determined by the comparison conditions\. For example, it can be as follows:

```cpp
bool equals_d(double lhs, double rhs, double eps)
{
  double diff = fabs(lhs - rhs);
  lhs = fabs(lhs);
  rhs = fabs(rhs);

  double largest = (rhs > lhs) ? rhs : lhs;

  return diff <= largest * eps;
}
```

**The case N3**\. Character arrays\. Look at the example:

```cpp
bool equals(const char *lhs, const char *rhs, size_t length)
{
  return memcmp(lhs, rhs, length) == 0;
}
```

When you use `memcmp` to compare character arrays, the [null character](https://pvs-studio.com/en/blog/terms/0088/) at the end of a string may be interpreted as data rather than a signal to stop the algorithm\. Because of this, either an incorrect comparison may occur, or the comparison may go beyond the array bounds, leading to [undefined behavior](https://pvs-studio.com/en/blog/terms/0066/)\.

The correct way to compare character arrays:

```cpp
bool equals(const char *lhs, const char *rhs, size_t length)
{
  return strncmp(lhs, rhs, length) == 0;
}
```