2016-12-12 2 views
1

Я прочитал следующий программный код:Какой смысл писать (void *) перед целым указателем?

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


int main() { 
    int *p; 
    p= malloc(sizeof(int)); 
    *p=42; 

    printf("Pointer p has address %p and points to %p\n", 
    (void*)&p, (void*)p); 

    free(p);  

} 

Мой вопрос относится к следующей части:

printf("Pointer p has address %p and points to %p\n", (void*)&p, (void*)p); 

Я не понимаю, что (void*) делает. Это ли? Какой смысл делать это?

В чем отличие вышеуказанного от простого написания следующего?

printf("Pointer p has address %p and points to %p\n", &p, p); 

ответ

10

Это потому, что %pявно ожидает аргумент типа void *.

Цитирование C11, глава §7.21.6.1, fprintf()

p Аргумент должен быть указателем на void. [....]

С printf() является вариационной функцией, и для указателей нет поощрения аргументов по умолчанию, требуется литье.

Строго говоря, согласно стандартным мандатом, с той же главы, пункт 7

[...] Если какой-либо аргумент не правильный тип для соответствующей спецификации преобразования, поведение не определено ,

Тем не менее, чтобы сделать ответ полным,

  • p = malloc(sizeof(int)); можно переписать в виде p= malloc(sizeof*p);, чтобы сделать его более устойчивым.
  • Перед использованием возвращаемого указателя всегда следует проверять успех malloc().
+0

@Sourav Ghoush: Спасибо за ваш ответ. Однако программа также работает без приведения (void *). Таким образом, для% p не нужно указывать указатель на void (вместо, скажем, указателя int), как это не представляется необходимым. –

+2

Иногда вы получаете «счастливый», а UB делает то, что вы ожидаете. – George

+2

@steady_progress: без приведения, поведение * undefined *, так как тип аргумента не совпадает с тем, что ожидает спецификатор преобразования - он может работать, он может и не работать. Если 'sizeof (int *)!= sizeof (void *) ', то вы, вероятно, получите искаженный вывод. –

1

Я не понимаю, что делает (void *). Это ли? Какой смысл делать это?

Да, это отливка. Это, кажется, не будет необходимости с моим компилятором (LLVM), что дает следующий результат, даже если я удалить слепки:

Pointer p has address 0x7fff501357d8 and points to 0x7fcb38c00390 

Другие компиляторы не могут быть настолько снисходительными.

Смежные вопросы