scanf и спецификатор преобразования p

В спецификации C11 сказано, что тип аргумента %p должен быть void ** в случае функции scanf(), но я не могу понять, как ввести адрес и сохранить его в void **. На самом деле, если я попытаюсь сделать:

void **p;
scanf("%p", p);

Я получаю ошибку сегментации.

P.S. Спецификация C11:

Соответствующий аргумент должен быть указателем на указатель на void


person xdevel2000    schedule 29.12.2014    source источник
comment
Я не понимаю, каков фактический вариант использования этого scanf() жесткого кодирования адреса для какой цели? у вас есть MC, где вы знаете фактические местоположения, в которые вам нужно сканировать значения? p - это двойной указатель, и его нужно сделать так, чтобы он указывал на указатель, который мы не видим в показанном коде.   -  person Gopi    schedule 29.12.2014
comment
@Gopi, да, я знаю, и на самом деле я не понимаю, почему стандарт говорит использовать двойной указатель!   -  person xdevel2000    schedule 29.12.2014
comment
Я прошу вас не изменять свой вопрос таким образом, чтобы ранее отправленные ответы выглядели неправильно. Рассмотрите возможность добавления дополнительной информации, оставив исходное сообщение без изменений. Кроме того, задавая вопрос, относящийся к конкретному стандарту, используйте соответствующий тег.   -  person Sourav Ghosh    schedule 29.12.2014


Ответы (4)


ПРИМЕЧАНИЕ. В исходном сообщении не упоминался стандарт c11.

Что ж, согласно документу спецификации c99, глава 7.19.6.12, параграф 812,

p

Соответствует определенному реализацией набору последовательностей, который должен совпадать с набором последовательностей, которые могут быть созданы преобразованием %p функции fprintf. Соответствующий аргумент должен быть указателем на указатель на void. Элемент ввода преобразуется в значение указателя способом, определяемым реализацией. Если входной элемент представляет собой значение, преобразованное ранее во время выполнения той же программы, полученный указатель должен быть равен этому значению; в противном случае поведение преобразования %p не определено.

Значит, это не void **, а void *.

Далее Причиной ошибки сегментации является использование неинициализированного указателя p в scanf(). Вы не выделили память для p перед тем, как [передали ее в scanf() в качестве аргумента].

Как предлагали другие, вы можете хорошо использовать что-то вроде

void *p;
scanf("%p", &p);

здесь значение &p на самом деле равно pointer to a pointer to void и имеет определенный адрес.

person Sourav Ghosh    schedule 29.12.2014
comment
В спецификации C11 сказано: соответствующий аргумент должен быть указателем на указатель на void - person xdevel2000; 29.12.2014
comment
@ xdevel2000 хорошо, причиной ошибки сегментации является использование неинициализированного указателя. - person Sourav Ghosh; 29.12.2014
comment
7.19.6.1 — это fprintf, а не fscanf. - person mafso; 29.12.2014
comment
@mafso Большое спасибо. Я действительно должен был быть осторожен. Обновленный ответ с исправлением. - person Sourav Ghosh; 29.12.2014
comment
Для чего вообще можно было бы использовать %p? - person S.S. Anne; 02.01.2020

void **p;
scanf("%p", p);

не работает по той же причине

int *i;
scanf("%i", i);

не работает - вы пишете в неинициализированный указатель (или, по крайней мере, говорите scanf писать в один).

Это работает:

int i;
scanf("%i", &i);

и так делает это:

void *p;
scanf("%p", &p);
person user253751    schedule 29.12.2014

Вы не инициализировали p. Пытаться:

void *p;
scanf("%p", &p);

Это берет адрес p, который действителен.

person FRob    schedule 29.12.2014

Стандарт говорит, что %p должен иметь аргумент типа void *. Вам нужно объявить p как void *, а затем

scanf("%p", &p);    

Причина, по которой вы получаете segfault, заключается в том, что в void **p p никуда не указывает.

person haccks    schedule 29.12.2014