The function ``++memcmp++`` only returns meaningful results for objects of trivially copyable types without padding. This includes scalar types, arrays, and trivially copyable classes.

== Why is this an issue?

`memcmp` compares the raw memory representation of two objects (what the standard calls their _object representation_). When objects are not trivially copyable or contain padding, they could have different raw memory representations even though they store identical values. So the result of `memcmp` is not meaningful.

Padding refers to the insertion of additional bits into a structure or class to ensure proper alignment of its members in memory. 

include::../../../shared_content/cfamily/trivially_copyable_types.adoc[]

== How to fix it

The comparison operator `operator==` should be defined and used instead of `memcmp` when the types are not trivially copyable or contain padding.
This allows comparing member by member to check object equality.

=== Code examples

==== Noncompliant code example

[source,c,diff-id=1,diff-type=noncompliant]
----
struct Shape { // Trivially copyable, but will contain padding after the bool on most architectures
  bool visible;
  int x;
  int y;
};

bool isSame(Shape *s1, Shape *s2)
{
    return memcmp(s1, s2, sizeof(Shape)) == 0; // Noncompliant
}
----

==== Compliant solution

[source,c,diff-id=1,diff-type=compliant]
----
struct Shape { // Trivially copyable, but will contain padding after the bool on most architectures
  bool visible;
  int x;
  int y;
};

bool isSame(Shape *s1, Shape *s2)
{
  return s1->visible == s2->visible && s1->x == s2->x && s1->y == s2->y;
}
----

==== Noncompliant code example

[source,cpp,diff-id=2,diff-type=noncompliant]
----
class Resource { // Not trivially copyable
public:
  Ptr* ptr;
  ~Resource();
};

bool isSame(Resource *r1, Resource *r2)
{
    return memcmp(r1, r2, sizeof(Resource)) == 0; // Noncompliant
}
----

==== Compliant solution

[source,cpp,diff-id=2,diff-type=compliant]
----
class Resource { // Not trivially copyable
public:
  Ptr* ptr;
  ~Resource();
};

bool operator==(Resource const &r1, Resource const &r2) {
  return r1.ptr == r2.ptr;
}

bool isSame(Resource *r1, Resource *r2)
{
    return (*r1) == (*r2);
}
----

== Resources

=== Documentation

* {cpp} reference - https://en.cppreference.com/w/cpp/language/classes#Trivially_copyable_class[Definition of a trivially copyable class].

=== Related rules

* S4999 - "memcpy", "memmove", and "memset" should only be called with pointers to trivially copyable types

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Use "operator==" to check object equality, "XXX" is not a trivially copyable type without padding.

Compare member by member to check object equality, "XXX" contains padding.


'''
== Comments And Links
(visible only on this page)

=== on 6 Nov 2018, 20:43:32 Ann Campbell wrote:
Double-check me [~loic.joly]

=== on 7 Nov 2018, 08:57:39 Loïc Joly wrote:
Looks good to me.

endif::env-github,rspecator-view[]
