проблемы с печатью указателей на аннулирование структуры

#include <stdio.h>

typedef struct elem{

    void * d;

}Elem;

main(){

    Elem *p;
    Elem e;

    double pi = 3.14;

    e.d = &pi;
    p->d = &pi;

    printf("%f\n",p->d);
    printf("%f\n",e.d);


}

main.c: 25: предупреждение: формат «% f» предполагает тип «double», но аргумент 2 имеет тип «void *»

main.c: 26: предупреждение: формат «% f» предполагает тип «double», но аргумент 2 имеет тип «void *»

У меня проблемы с попыткой правильно распечатать эти значения. Я получаю значения, не имеющие ничего общего с 3.14.


person Jaime38130    schedule 28.01.2016    source источник
comment
@im также UB. %f берет дубль. Это также UB, потому что объект, на который он указывает, - это double. Это нарушает строгое правило псевдонима.   -  person too honest for this site    schedule 28.01.2016


Ответы (2)


В вашем коде, во-первых, вам нужно выделить память для p, прежде чем разыменовать его. В противном случае он вызывает неопределенное поведение. В противном случае p является унифицированным указателем и указывает на мемориал, который может быть недоступен из вашей программы, что, по сути, является недопустимым местом в памяти. Любая попытка разыменования этого указателя вызовет UB.

После этого,

  printf("%f\n",p->d);
  printf("%f\n",e.d);

вызывает неопределенное поведение, поскольку вы, по сути, пытаетесь напечатать адрес с помощью спецификатора формата %f.

Что вам нужно сделать, это

  1. приведите указатель void к указателю float (потому что вы не можете разыменовать void *)

  2. а затем разыменуйте указатель, чтобы получить значение.

Нравится

  printf("%f\n",*((float *)(p->d)));
  printf("%f\n",*((float *)e.d));    

Тем не менее, main() должно быть int main(void), по крайней мере, чтобы быть стандартной жалобой.

person Sourav Ghosh    schedule 28.01.2016
comment
Что вам нужно сделать, так это привести указатель к float ...... потому что вы не можете разыменовать указатель void. - person haccks; 28.01.2016
comment
@haccks Да, сэр, это то, что я хотел написать. Означает ли моя формулировка иное? - person Sourav Ghosh; 28.01.2016
comment
Нет. Я просто предложил добавить это в свой ответ. Жду голосования. - person haccks; 28.01.2016
comment
@haccks Спасибо. :) - person Sourav Ghosh; 28.01.2016
comment
Пожалуйста. Вы также можете принять ответ, который вам помог. - person Sourav Ghosh; 29.01.2016

Вы не можете:

Elem *p;
[...]
double pi = 3.14;
[...]
p->d = &pi;

... потому что p никуда не указывает. В лучшем случае поведение вашей программы будет неопределенным, но в лучшем случае произойдет сбой. Правильный код, который, как мне кажется, вы хотите достичь:

#include <stdio.h>
#include <stdlib.h>

typedef struct elem {
    void * d;
} Elem;

int main(void) {
    double pi = 3.14;
    // make p point to allocated memory
    Elem *p = malloc(sizeof(*p));
    p->d = &pi;
    // notice the %lf and *(double *)
    // %f is for floats, %lf is four doubles
    // and *(double *) means 'use the value of the pointer (the d field)
    // as the pointer to double type. And then use the value it points to
    printf("%lf\n", *(double *)(p->d));
    return 0;
}
person nsilent22    schedule 28.01.2016