Получение странного O / P при попытке напечатать значения структуры в C - PullRequest
1 голос
/ 27 июля 2011
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct info
{
        int id;
        char name[20];
};

int main()
{
        struct info p;
        struct info *ptr;

        ptr = &p;


        (*ptr).id = 20;
        strcpy((*ptr).name, "Delluh");


        printf("\n %u %u %u\n\n",*ptr,ptr->id,ptr->name);



        return 0;

}

Последнее выражение printf дает мне вывод '20 1819043140 26741', из которых 20 является правильным значением, а оставшиеся 2 значения являются некоторыми значениями мусора. Однако при удалении * из ptr я получаю правильный вывод значения адреса 20, а затем другого значения адреса. Может кто-нибудь сказать мне, почему размещение * перед ptr приводит к путанице в двух других значениях?

Ответы [ 2 ]

0 голосов
/ 11 января 2012

Потому что, имея *, вы разыменовываете структуру и передаете все это - id и name & mdash.

Printf использует varargs, что в основном означает, что вы можете передать как можно больше аргументовлюбой тип, который вы хотите, но это также означает, что компилятор не будет выполнять никакого автоматического преобразования типов или проверки для вас (потому что он не знает, какие типы ожидать).Таким образом, аргументы, которые вы передаете, просто заканчиваются как последовательность байтов в стеке, а строка формата сообщает printf, как интерпретировать эту строку байтов.Среди прочего, он сообщает, сколько байтов нужно пропустить, чтобы перейти к следующему аргументу.

Итак, вы хотели ptr->id первый аргумент, который составляет всего 4 байта.Но вы фактически передали все 24 байта структуры в качестве аргумента.Таким образом, после того как printf завершил печать первых 4 байтов как целое число без знака, он был готов напечатать следующий аргумент, но все еще застрял в начале поля имени.Если вы посмотрите, то напечатанное значение «мусора» равно 0x6C6C6544, что представляет собой 4 символа ASCII «lleD», то есть ваша строка, интерпретируемая как целое число с прямым порядком байтов.

В общем, вы, вероятно, можете убежатьс извлечением первого поля из структуры, просто разыменовав указатель (указатель указывает как на структуру, так и на ее первое поле), но только если компилятор знает, что это то, что вы пытаетесь сделать на основе типа.Например, это, вероятно, будет работать:

int id = *ptr;

Технически, это, по крайней мере, может сработать, потому что компилятор знает, к какому типу вы на самом деле пытаетесь добраться.Реально, компилятор, вероятно, выдаст ошибку или предупреждение, и вам нужно будет выполнить приведение.

0 голосов
/ 27 июля 2011

Не было бы более загадочным, если бы вы использовали это

printf("\n %p %i %s\n\n",ptr,ptr->id,ptr->name);

Вы используете% u (целое число без знака) в printf для всех параметров, но передаете указатель, целое число и строковый параметрЯ думаю, что это проблема, которую вы имеете.Вам следует взглянуть на документацию printf о том, что означают параметры% s,% u,% i и т. Д.

...