The C Standard, 6.7.3.2 paragraph 19 [ISO/IEC 9899:2024], states
There may be unnamed padding within a structure object, but not at its beginning. . . . There may be unnamed padding at the end of a structure or union.
Subclause 6.7.11, paragraph 10, states that
unnamed members of objects of structure and union type do not participate in initialization. Unnamed members of structure objects have indeterminate representation even after initialization.
The only exception is that padding bits are set to zero when a static or thread-local object is implicitly initialized (paragraph 11):
If an object that has static or thread storage duration is not initialized explicitly, or any object is initialized with an empty initializer, then it is subject to default initialization, which initializes an object as follows:
— if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits.
Because these padding values are unspecified, attempting a byte-by-byte comparison between structures can lead to incorrect results [Summit 1995].
Noncompliant Code Example
In this noncompliant code example, memcmp() is used to compare the contents of two structures, including any padding bytes:
#include <string.h>
struct s {
char c;
int i;
char buffer[13];
};
void compare(const struct s *left, const struct s *right) {
if ((left && right) &&
(0 == memcmp(left, right, sizeof(struct s)))) {
/* ... */
}
}
Compliant Solution
In this compliant solution, all of the fields are compared manually to avoid comparing any padding bytes:
#include <string.h>
struct s {
char c;
int i;
char buffer[13];
};
void compare(const struct s *left, const struct s *right) {
if ((left && right) &&
(left->c == right->c) &&
(left->i == right->i) &&
(0 == memcmp(left->buffer, right->buffer, 13))) {
/* ... */
}
}
Exceptions
EXP42-C-EX1: A structure can be defined such that the members are aligned properly or the structure is packed using implementation-specific packing instructions. This is true only when the members' data types have no padding bits of their own and when their object representations are the same as their value representations. This frequently is not true for the _Bool type or floating-point types and need not be true for pointers. In such cases, the compiler does not insert padding, and use of functions such as memcmp() is acceptable.
This compliant example uses the #pragma pack compiler extension from Microsoft Visual Studio to ensure the structure members are packed as tightly as possible:
#include <string.h>
#pragma pack(push, 1)
struct s {
char c;
int i;
char buffer[13];
};
#pragma pack(pop)
void compare(const struct s *left, const struct s *right) {
if ((left && right) &&
(0 == memcmp(left, right, sizeof(struct s)))) {
/* ... */
}
}
Risk Assessment
Comparing padding bytes, when present, can lead to unexpected program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
EXP42-C | Medium | Probable | Medium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description |
|---|---|---|---|
| Astrée | 24.04 | memcpy-with-padding | Partially checked |
| Axivion Bauhaus Suite | 7.2.0 | CertC-EXP42 | |
| CodeSonar | 9.1p0 | BADFUNC.MEMCMP | Use of memcmp |
| Cppcheck Premium | 24.11.0 | premium-cert-exp42-c | Fully implemented |
| Helix QAC | 2025.2 | DF4726, DF4727, DF4728, DF4729 | |
| Klocwork | 2025.2 | MISRA.STDLIB.MEMCMP.PTR_ARG_TYPES | |
| LDRA tool suite | 9.7.1 | 618 S | Partially implemented |
| Cppcheck | 2.15 | cert.py | Detected by the addon cert.py Does not warn about global/static padding data as this is probably initialized to 0 |
| Parasoft C/C++test | 2024.2 | CERT_C-EXP42-a | Don't memcpy or memcmp non-PODs |
| PC-lint Plus | 1.4 | 958, 959 | Assistance provided: reports structures which require padding between members or after the last member |
R2025b | Checks for memory comparison of padding data (rule fully covered) | ||
| PVS-Studio | 7.39 | V1103 | |
| RuleChecker | 24.04 | memcpy-with-padding | Partially checked |
| TrustInSoft Analyzer | 1.38 | comparable_char_blocks | Exhaustively verified (see the compliant and the non-compliant example). |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| ISO/IEC TS 17961 | Comparison of padding data [padcomp] | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CERT C | EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
| [ISO/IEC 9899:2024] | 6.7.3.2, "Structure and Union Specifiers" 6.7.11, "Initialization" |
| [Summit 1995] | Question 2.8 Question 2.12 |


