У вас 2 большие проблемы с вашим кодом: вы смешиваете типы.
В DOS_HEADER
все члены (кроме последнего) имеют тип unsigned short
.
Это важно.
В get_dos_header
вы делаете
fread(fp_buffer, 2, 1, fp);
raw_info_dos_header.e_magic = fp_buffer;
что не так.
- Не используйте магические числа, используйте
sizeof
, чтобы получить правильные размеры
- Проверьте возвращаемое значение
fread
, особенно если вы анализируете двоичный файл
формат, вы должны быть уверены, что вы прочитали именно то, что вы ожидаете.
- Намного легче иметь дело с
fread
, когда аргумент size
равен 1, потому что
только когда аргумент size
равен 1, возвращаемое значение fread
соответствует
количество прочитанных байтов.
e_magic
- это unsigned short
, fp_buffer
- это char*
. Это назначение
не копируя содержимое, указанное fp_buffer
, вы сохраняете адрес
как если бы это было значение unsigned short
. Вам нужно скопировать указанную память
fp_buffer
.
Также я не вижу смысла в том, чтобы вы выделяли буфер размером с файл
когда вы читаете кусок за куском. Было бы проще, если бы вы не выделяли
создайте буфер и используйте массив размером больше, чем вы собираетесь читать.
int get_dos_header(FILE* fp, DOS_HEADER *dos)
{
unsigned char buffer[8];
size_t ret = fread(buffer, 1, sizeof(dos->e_magic), fp);
if(ret != sizeof(dos->e_magic))
{
fprintf(stderr, "Invalid file size\n");
return 0;
}
memcpy(&dos->e_magic, buffer, sizeof(dos->e_magic));
// DO the others fread operation
...
return 1;
}
Тогда в main
вы можете сделать это:
DOS_HEADER raw_info_dos_header = {0, };
if(get_dos_header(fp, &raw_info_dos_header) == 0)
{
fprintf(stderr, "failed to get the DOS header\n");
return 1;
}
...
Вторая проблема в print_data_of_structures
:
printf("%s", info_dos_header.e_magic);
e_magic
- это unsigned short
, %s
ожидает указатель на char
, он ожидает
строка. e_magic
определенно не строка. Это приводит к неопределенному поведению.
printf
должно выглядеть так:
printf("e_magic: %hu\n", info_dos_header.e_magic);
или
printf("e_magic: 0x%04hx\n", info_dos_header.e_magic);
чтобы распечатать его в шестнадцатеричном формате.
Я также советую вам вместо этого использовать указатели. Ваша структура большая и передает
указатель на функцию намного дешевле, чем передача большой структуры в
функции. Так что вместо
void print_data_of_structures(DOS_HEADER info_dos_header);
объявить его как
void print_data_of_structures(DOS_HEADER *info_dos_header);
А также не объявляйте функцию, которая может завершиться ошибкой (например, get_dos_header
), как
void
, иначе как вы скажете вызывающей функции, что она не сработала? Это
лучше для таких функций вернуть int
(1 для успеха, 0 для отказа) и
ожидать указатель на структуру, где хранится информация (см., как я
изменено get_dos_header
выше.