The C99 standard, section 6.2.6.1 8, states:
When an operator is applied to a value that has more than one object representation, which object representation is used shall not affect the value of the result (43). Where a value is stored in an object using a type that has more than one object representation for that value, it is unspecified which representation is used, but a trap representation shall not be generated.
I understood object to mean a location (bytes) in memory and value as the interpretation of those bytes based on the type used to access it. If so, then:
The standard adds the below in the footnote:
Still, it's not clear to me. Can someone please simplify it for me and explain with examples?
An object is a region of storage (memory) that can contain values of a certain type [C18 3.15].
An object representation are the Bytes that make up the contents of an object [C18 6.2.6.1].
Not every possible combination of Bytes in an object representation also has to correspond to a value of the type (an object representation that doesn't is called a trap representation [C18 3.19.4]).
And not all the Bits in an object representation have to participate in representing a value. Consider the following type:
struct A
{
char c;
int n;
};
Compilers are allowed to (and generally will) insert padding Bytes between the members c
and n
of this struct to ensure correct alignment of n
. These padding Bytes are part of an object of type struct A
. They are, thus, part of the object representation. But the values of these padding Bytes do not have any effect on the logical value of type A
that is stored in the object.
Let's say we're on a target platform where Bytes consist of 8 Bits, an int
consists of 4 Bytes in little endian order, and there are 3 padding Bytes between c
and n
to ensure that n
starts at an offset that is a multiple of 4. The value (struct A){42, 1}
may be stored in an object as
2A 00 00 00 01 00 00 00
But it may as well be stored in an object as
2A FF FF FF 01 00 00 00
or whatever else the padding Bytes may happen to be. Each of these sequences of Bytes is a valid object representation of the same logical value of type struct A
.
This is also what the footnote is about. If you had two objects x
and y
that each contained a different object representation of the same value of type struct A
, then x == y
will evaluate to true while simply performing a memcmp()
will not since memcmp()
simply compares the bytes of the object representation without any consideration as to what the logical value stored in these objects actually is…