Потому что, имея *
, вы разыменовываете структуру и передаете все это - id и name & mdash.
Printf использует varargs, что в основном означает, что вы можете передать как можно больше аргументовлюбой тип, который вы хотите, но это также означает, что компилятор не будет выполнять никакого автоматического преобразования типов или проверки для вас (потому что он не знает, какие типы ожидать).Таким образом, аргументы, которые вы передаете, просто заканчиваются как последовательность байтов в стеке, а строка формата сообщает printf, как интерпретировать эту строку байтов.Среди прочего, он сообщает, сколько байтов нужно пропустить, чтобы перейти к следующему аргументу.
Итак, вы хотели ptr->id
первый аргумент, который составляет всего 4 байта.Но вы фактически передали все 24 байта структуры в качестве аргумента.Таким образом, после того как printf завершил печать первых 4 байтов как целое число без знака, он был готов напечатать следующий аргумент, но все еще застрял в начале поля имени.Если вы посмотрите, то напечатанное значение «мусора» равно 0x6C6C6544, что представляет собой 4 символа ASCII «lleD», то есть ваша строка, интерпретируемая как целое число с прямым порядком байтов.
В общем, вы, вероятно, можете убежатьс извлечением первого поля из структуры, просто разыменовав указатель (указатель указывает как на структуру, так и на ее первое поле), но только если компилятор знает, что это то, что вы пытаетесь сделать на основе типа.Например, это, вероятно, будет работать:
int id = *ptr;
Технически, это, по крайней мере, может сработать, потому что компилятор знает, к какому типу вы на самом деле пытаетесь добраться.Реально, компилятор, вероятно, выдаст ошибку или предупреждение, и вам нужно будет выполнить приведение.