2017-02-10 3 views
2

От стандарта C11 (проект): 7.21.6.2/12:Использования Scanf% р UB

Если элемент ввода является значением, преобразованным ранее при той же программе выполнения, указатель, что результаты сравнят равны это значение; В противном случае поведение преобразования% p не определено.

Может кто-нибудь предоставить код для этой части стандарта, пожалуйста. Не могу понять, как получить %p с ввода.

+3

Если у вас есть указатель-переменная 'p', printf с помощью преобразования'% p', а затем скопировать, вставить и scanf, используя одно и то же преобразование '% p' в другую переменную-указатель' q' в том же процессе, тогда 'р == q'. – DyZ

+0

Вы не хотите, например, «printf» вывести сегментированные значения указателя 8088, такие как «5: abcd», и отсканировать их на плоской архитектуре 386. – alk

+1

Обратите внимание, что успешное перемещение указателя указателя -> text -> приведет к указателю, который «сравнивает (равно) с этим значением». У исходных и конечных указателей все еще могут быть разные битовые кодировки, но эквивалентные _values_, как и '+0.0 == -0.0' Детали зависят от платформы. – chux

ответ

5

Во-первых, вот небольшой демо, которая использует строковые варианты ввода и вывода (demo):

int val = 123; 
char buf[100]; 
sprintf(buf, "%p", (void*)&val); 
printf("Original =%s\n", buf); 
void *ptr; 
sscanf(buf, "%p", &ptr); 
printf("Read back=%p\n", ptr); 
int *iPtr = ptr; 
if (iPtr == &val) { 
    printf("Pointers match\n"); 
} 

sprintf сверху записывает указатель на выходной буфер; sscanf читает его обратно.

Строка подается в sscanf спичек точно строка, которая была произведена sprintf, поэтому стандарт гарантирует, что iPtr == &val собирается оценить в true, а поведение определяется. Передача строки, которая не соответствует чему-либо, созданному одной и той же запущенной программой, будет неопределенным поведением.

+1

Вы уверены, что 'int * ptr;' и '... (void **) &ptr);' в порядке? Я думал, что 'void *' и 'int *' не должны быть одного размера. Я ожидал бы 'void * p; ... sscanf (buf, "% p", &p); ' – chux

+2

@chux Это отличный момент, спасибо вам большое! Вы правы, отливки достаточно хороши для' printf', но недостаточно хороши для 'scanf'. отредактировал ответ на эту учетную запись. – dasblinkenlight

+0

@chux Еще раз спасибо. Это не было иллюстрацией, это был случай «слишком много C++». – dasblinkenlight

0
int main(){ 
    int c =5; 
    int *p; 
    printf("Address of C: %p\n Please Enter the above address: " , &c); 
    scanf("%p", &p); 
    *p=10; 
    printf("\nNew value of C: %d", c); 
} 

Вы можете вручную установить указатели через scanf. Однако, если у вас есть опечатка.

+1

Закрыть, но тип указателя, напечатанного и отсканированного, не совсем прав. – chux

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