C memcpy для структурирования выделения - PullRequest
3 голосов
/ 30 октября 2019

Я написал простую программу для проверки копирования байтов из байтового буфера в структуру с использованием memcpy. Однако я не получаю ожидаемых результатов.

Я выделяю буфер из 100 байтов и устанавливаю значения 0, 1, 2 ... 99. Затем я копирую байты в структуру размером 16 байт.

Где-то теряется байт 0x01. Я пытаюсь понять, что происходит

#include <stdio.h>
#include <stdint.h>

struct Test {

    uint8_t a;
    uint16_t b;
    uint32_t c;
    uint64_t d;
    uint8_t e;
};

int main(int argc, char** argv) {

    uint8_t buffer[100];
    for (uint8_t i = 0; i < 100; i++) {
        buffer[i] = i;
    }

    struct Test test;
    memcpy(&test, buffer, sizeof(struct Test));

    printf("A is %ld and should be %ld\n", test.a, 0x00);
    printf("B is %ld and should be %ld\n", test.b, 0x0201);
    printf("C is %ld and should be %ld\n", test.c, 0x06050403);
    printf("D is %ld and should be %ld\n", test.d, 0x1413121110090807);
    printf("E is %ld and should be %ld\n", test.e, 0x15);
}

И я получаю результат:

A is 0 and should be 0
B is 770 and should be 513
C is 117835012 and should be 100992003
D is 1084818905618843912 and should be 1446519769808832519
E is 16 and should be 21

770 (значение B) это байты 0302, а не 0201 (int 513)

1 Ответ

5 голосов
/ 30 октября 2019

Причина этого в том, что компилятор добавил padding в вашу структуру, чтобы гарантировать, что b выровнено по 16-битной границе. Таким образом, второй байт не используется.

Вы увидите гораздо большее изменение, если начнете переупорядочивать свою структуру. Точно так же 32-битные и 64-битные значения будут хотеть выравнивание, соответствующее их типу. Таким образом, вы можете получить значительные «дыры» из-за заполнения. Попробуйте!

Часто вы увидите структуры, содержащие reserved членов (особенно для двоичных форматов), вместо того, чтобы полагаться на заполнение.

...