Как malloc
выделяет 24 байта для выравнивания памяти, поскольку мы просто передаем размер структуры (13 байтов)?
Это не так. Если malloc(13)
возвращает хотя бы 24 байта, это странная реализация malloc
. malloc
разрешено выделять больше места, чем необходимо, и часто необходимо для выравнивания байтов и различных других причин реализации.
Мы можем увидеть это с помощью простой программы.
struct st *a = malloc(13);
struct st *b = malloc(13);
struct st *c = malloc(13);
struct st *d = malloc(13);
printf("%p\n%p\n%p\n%p\n", a, b, c, d);
0x602000003210
0x602000003230
0x602000003250
0x602000003270
Как видно из адресов, указатели, возвращаемые malloc(13)
, имеют между собой 32 байта. Много, чтобы соответствовать вашим 24 байтов, и программа "работает". Даже malloc(1)
возвращает тот же результат.
Но если мы сделаем вашу структуру немного больше ...
struct st {
char c;
double b;
double a;
double d;
int i;
};
Это 40 байтов, выровненных. Теперь он не помещается в 32 байта, и мы видим искажение, потому что память структуры перекрывается друг с другом.
#include <stdlib.h>
#include <stdio.h>
struct st {
char c;
double b;
double a;
double d;
int i;
};
void print_struct(struct st* st) {
printf("%c %lf %d\n", st->c, st->d, st->i);
}
int main() {
const size_t struct_size = sizeof(char) + (sizeof(double) * 3) + sizeof(int);
printf("sizeof(struct st): %zu\n", sizeof(struct st));
printf("sizeof fields added together: %zu\n", struct_size);
struct st *a = malloc(13);
struct st *b = malloc(13);
struct st *c = malloc(13);
struct st *d = malloc(13);
printf("%p\n%p\n%p\n%p\n", a, b, c, d);
a->c = 'a';
a->d = 1.0;
a->i = 1;
b->c = 'b';
b->d = 2.0;
b->i = 2;
c->c = 'c';
c->d = 3.0;
c->i = 3;
d->c = 'd';
d->d = 4.0;
d->i = 4;
print_struct(a);
print_struct(b);
print_struct(c);
print_struct(d);
}
sizeof(struct st): 40
sizeof fields added together: 29
0x602000003210
0x602000003230
0x602000003250
0x602000003270
a 1.000000 98
b 2.000000 99
c 3.000000 100
d 4.000000 4
98 является b
. 99% 1027 *. 100% d
. Это означает, что a->i
перекрывается с b->c
, b->i
перекрывается с c->c
и т. Д.