Использование указателей void на разных платформах
Я слышал, что указатели сначала должны быть отброшены в void для обеспечения согласованности значений на разных платформах и должны использовать спецификатор формата %p
. Почему это и какие именно проблемы?
int x=100;
int *pi=&x;
printf("value of pi is: %p",(void*)pi);
Ответы
Ответ 1
printf
- это вариационная функция и должны быть переданы аргументы правильных типов. В стандарте говорится, что %p
принимает void *
.
Неявный бросок не выполняется для вариационных функций.
Цитата из N1570 7.21.6.1 Функция fprintf
p: Аргумент должен быть указателем на void. Значение указателя преобразованный в последовательность печатных символов, в определенном реализацией образом.
Ответ 2
Внутреннее представление или размер разных типов указателей не обязательно одинаково.
Например, в одной системе sizeof(void*)
может быть 2, но sizeof(int*)
равно 1.
Так как printf
- переменная функция аргумента, она не может проверять типы входящих параметров. Если вы передали ему int*
, он будет читать неправильное количество байтов, потому что он ожидает void*
.
Ответ 3
p
Спецификация преобразования в printf
требует аргумента типа void *
. C говорит, что если вы передаете аргумент другого типа, вызов вызывает поведение undefined.
Кроме того, для объектов-указателей разных типов не требуется одинаковое представление: C не гарантирует, что sizeof (void *) == sizeof (int *)
например. C гарантирует, что void *
имеет то же представление, что и указатели на типы символов.