Как работает функция scanf в C?
почему вам требуется амперсанд ( & ) в
7 ответов
на &
В C-оператор, возвращающий адрес операнда. Подумайте об этом так, если бы вы просто дали scanf
переменная a
без &
она будет передана ему по значению, что означает scanf
не сможете установить его значение для вас, чтобы увидеть. Передавая его по ссылке (используя &
, фактически передается указатель a
) позволяет scanf
чтобы установить его так, чтобы вызывающие функции тоже видели изменение.
относительно конкретной ошибки, ты не можешь точно сказать. Поведение не определено. Иногда, он может молча продолжать работать, без вашего ведома scanf
изменить какое-то значение где-то в вашей программе. Иногда это приведет к немедленному сбою программы, как в этом случае:
#include <stdio.h>
int main()
{
int a;
printf("enter integer: ");
scanf("%d",a);
printf("entered integer: %d\n", a);
return 0;
}
компиляция показывает следующее:
$ gcc -o test test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘int’
и выполнение показывает ошибку сегментации:
$ ./test
enter integer: 2
Segmentation fault
В C все аргументы функции передаются по значению; любые изменения формального параметра функции не отражаются в фактическом параметре. Например:
void foo(int bar)
{
bar = bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(x);
printf("x after foo = %d\n", x);
return 0;
}
выход программы будет
x before foo = 0 x after foo = 0
, потому что bar
получает значение x
(0), не Ссылка на . Меняется bar
не влияет на x
.
В C, путь вокруг этого должен пройти указатель в переменная:
void foo(int *bar)
{
*bar = *bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(&x);
printf("x after foo = %d\n", x);
return 0;
}
теперь выход программы
x before foo = 0 x after foo = 1
на этот раз, формальный параметр bar
не int, а a указатель в int, и он получает адрес of x
(дается выражением &x
в вызове foo
), а не значение, содержащееся в X. Выражение *bar
означает "получить значение в адресной строке указывает на", так *bar = *bar + 1
соответствует x = x + 1
.
С scanf()
необходимо записать его аргументы, он ожидает, что эти аргументы будут набраны как указатели. Спецификатор преобразования "%d " ожидает, что соответствующий аргумент будет указателем на int (int *
), спецификатор преобразования "%u " ожидает указатель на unsigned int (unsigned *
), "%s " ожидает указатель на char (char *
), "%f " ожидает, что указатель будет плавающим (float *
) и т. д. В вашем примере, так как a
введен int
, вам нужно использовать выражение &a
получить указатель.
обратите внимание, что если a
были уже типом указателя, вам не нужно было бы использовать &
оператор в вызове scanf()
:
int main(void)
{
int a, *pa; // declare pa as a pointer to int
...
pa = &a; // assign address of a to pa
scanf("%d", pa); // scanf() will write to a through pa
...
}
Также обратите внимание, что при передаче массива функции (например, при использовании спецификатора преобразования "%s" для чтения строки) вам не нужно использовать &
оператор; выражение массива будет неявно преобразовано в тип указателя:
int main(void)
{
char name[20];
...
scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
...
}
Если вы задаете такой вопрос, я бы рекомендовал просто учиться сейчас "это просто делает".
вы узнаете, что вам нужен амперсанд, потому что scanf
принимает один или несколько аргументов указатель. Если a-переменная int, это не указатель. &a ("адрес a") является указателем, поэтому он будет работать с scanf
.
это потому, что в C параметры функций являются передан по значению. Для того, чтобы scanf()
функция для изменения'a
' переменная в вашей функции main (),адрес of'a
' будет дано scanf()
, следовательно, использование амперсанда (адрес).
, потому что scanf
требуется указатель на переменную (т. е. ссылку), в которую будет входить значение.
не всегда нужно использовать &
с scanf
. То, что вам нужно сделать, это пройти указатели. Если вы новичок в C, вы должны потратить некоторое время на чтение комп.ленг.с вопросы и ответы:
в частности:
" & " в scanf
требуется только для получения адреса переменной. Вы can использовать scanf
без '&' с помощью указателей:
int myInt;
int * pointer_to_int;
pointer_to_int = &myInt;
scanf("%d", pointer_to_int);
В общем, использование " & "часто проще, чем создание указателя, чтобы избежать использования"&".