Эта программа проверяет, можно ли использовать указатель в качестве переменной для хранения входных данных.
#include <stdio.h>
int main(void)
{
int *prt;
printf("Input prt:");
scanf("%d", prt);
printf("What you inputed is: %d\n", *prt);
return 0;
}
И терминальный журнал:
Segmentation fault (core dumped)
Затем я написал еще один тест:
#include <stdio.h>
int main(void)
{
int *p;
int x;
printf("Input x:");
scanf("%d", &x);
p = &x;
printf("What you inputed is: %d\n", x);
printf("What you inputed is: %d\n", *p);
printf("The address of x: %p\n", &x);
printf("The address p points to: %p\n", p);
return 0;
}
И терминальный журнал:
Input x:10
What you inputed is: 10
What you inputed is: 10
The address of x: 0x7ffc5f2636f4
The address p points to: 0x7ffc5f2636f4
Это работает хорошо. Итак, я запутался, почему я не могу использовать prt первой программы для приема ввода?
Функция scanf ожидает, что указатель действительно куда-то указывает (действительно). В вашей первой программе prt не указывает ни на что особенное, и разыменование этого указателя (что scanf и делает) приводит к неопределенному поведению.
Во второй программе присваивание p = &x заставляет указатель p указывать на x.
А как простой способ визуализировать указатели, возьмите лист бумаги и нарисуйте на нем два прямоугольника. Подпишите одну коробку p и другую x. Теперь нарисуйте стрелку от p до x, чтобы стрелка указывала на x. Примерно так работают указатели и присваивание p = &x. Чтобы визуализировать первый пример, нарисуйте прямоугольник и назовите его prt. Теперь нарисуйте стрелку от этой коробки к пустому клочку бумаги. Это показывает, что prt ни на что не указывает.





Ваша переменная prt является указателем на целое число, но на самом деле она не инициализируется действительным адресом памяти, на который можно было бы указать, поэтому попытка прочитать ее с помощью scanf вызывает неопределенное поведение. Одним из вероятных результатов является ошибка сегментации, но нельзя предполагать, что это приведет к ошибке сегментации.
Ваш второй пример работает, потому что &x действительно указывает на x, и поэтому мы можем его прочитать.
scanf (с %d) требует действительный адрес int (для заполнения проанализированного поля).
Эта строка:
int *prt;
Объявляет prt указатель на int, но он не инициализируется и, следовательно, не указывает ни на какой действительный int.
Результатом является неопределенное поведение — может случиться что угодно, включая (но не обязательно) ошибку сегментации.
В вашем втором случае:
int x;
x объявлен как int (а не указатель на int), и поэтому &x является допустимым адресом для scanf.
Примечание: scanf возвращает количество успешно проанализированных полей. Вы всегда должны проверять его (в вашем случае 1), чтобы убедиться, что все прошло успешно.
Указатель должен на что-то указывать.