You can use the offsetof()
macro to find the offset in bytes of each field from the first member (which must have the same address as the struct
since no padding is allowed to precede the first member).
Combining this information with the sizes of the various members (and the size of the whole struct
to find the number of trailing padding bytes), obtained using the sizeof
operator, allows one to deduce where the padding bytes are. Here is a program that prints out member addresses and offsets. It also prints a graphic representation of member bytes and padding bytes; dashes indicate padding bytes.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
struct simple_struct_1 {
long long a;
char b;
long c;
};
char * graph_member(char *ptr, size_t member_sz, size_t padding_sz);
int main(void)
{
struct simple_struct_1 my_struct;
printf("sizeof (struct simple_struct_1) = %zu\n",
sizeof (struct simple_struct_1));
putchar('\n');
void *ptra = &(my_struct.a);
void *ptrb = &(my_struct.b);
void *ptrc = &(my_struct.c);
size_t offset_a = offsetof(struct simple_struct_1, a);
size_t offset_b = offsetof(struct simple_struct_1, b);
size_t offset_c = offsetof(struct simple_struct_1, c);
/* Allocate memory for struct padding visualization */
char *graph = malloc(sizeof my_struct + 1);
if (graph == NULL) {
perror("Virtual memory exhausted");
exit(EXIT_FAILURE);
}
char *ptr = graph;
printf("&(my_struct.a) = %p\n", ptra);
printf("sizeof my_struct.a = %zu\n", sizeof my_struct.a);
putchar('\n');
ptr = graph_member(ptr,
sizeof my_struct.a,
offset_b - sizeof my_struct.a);
printf("&(my_struct.b) = %p\n", ptrb);
printf("sizeof my_struct.b = %zu\n", sizeof my_struct.b);
printf("&(my_struct.b) - &(my_struct.a) = %zu\n", offset_b - offset_a);
putchar('\n');
ptr = graph_member(ptr,
sizeof my_struct.b,
offset_c - offset_b - sizeof my_struct.b);
printf("&(my_struct.c) = %p\n", ptrc);
printf("sizeof my_struct.c = %zu\n", sizeof my_struct.c);
printf("&(my_struct.c) - &(my_struct.b) = %zu\n", offset_c - offset_b);
putchar('\n');
ptr = graph_member(ptr,
sizeof my_struct.c,
sizeof my_struct - offset_c - sizeof my_struct.c);
/* Null-terminate graph string and display */
ptr = '\0';
puts(graph);
free(graph);
return 0;
}
char * graph_member(char *ptr, size_t member_sz, size_t padding_sz)
{
/* Indicate member */
for (size_t i = 0; i < member_sz; i++) {
*ptr = '*';
++ptr;
}
/* Indicate padding */
for (size_t i = 0; i < padding_sz; i++) {
*ptr = '-';
++ptr;
}
return ptr;
}
Sample program output:
sizeof (struct simple_struct_1) = 24
&(my_struct.a) = 0x7ffee4af4610
sizeof my_struct.a = 8
&(my_struct.b) = 0x7ffee4af4618
sizeof my_struct.b = 1
&(my_struct.b) - &(my_struct.a) = 8
&(my_struct.c) = 0x7ffee4af4620
sizeof my_struct.c = 8
&(my_struct.c) - &(my_struct.b) = 8
*********-------********