2016-12-08 3 views
-1

У меня есть следующий вопрос с множественным выбором, и я не могу понять, почему (A) и (C) неверны, любое объяснение будет оценено! Единственным правильным ответом в следующем вопросе является (B).Амперсанд (&) и scanf в C?

Which of the following is a correct usage of scanf? 
(A) int i=0; scanf("%d", i); 
(B) int i=0; int *p=&i; scanf("%d", p); 
(C) char *s="1234567"; scanf("%3s", &s); 
(D) char c; scanf("%c", c); 
+4

Вы прочитали [ссылку] (http://en.cppreference.com/w/cpp/io/ с/fscanf)? – UnholySheep

+0

'scanf' необходимо изменить переменные, обратившись к памяти. Для этого нужен адрес. Поэтому подумайте, в каких примерах он фактически получает действительный адрес. – StoryTeller

+0

Есть ли случаи, когда амперсанд или ссылка не нужны? Я чувствую, что видел примеры, опуская &, но, возможно, я ошибаюсь. Я думал, что ссылки нужны только для строк и массивов по какой-то причине. – Nuggets10

ответ

4

scanf хочет правильный адрес, куда сохранить результат:

(A) int i=0; scanf("%d", i); 

i передается здесь по значению, без адреса: неправильно.

(B) int i=0; int *p=&i; scanf("%d", p); 

p является указателем на Int, scanf может хранить свой результат здесь: правый

(C) char *s="1234567"; scanf("%3s", &s); 

&s является адресом указателя на char *, вы не можете хранить строку там: неправильно

(D) char c; scanf("%c", c); 

c передается по значению, а не по адресу: неверно

+0

Спасибо, теперь намного больше смысла. Похоже, мне нужно более внимательно изучить функцию scanf. – Nuggets10

+0

Да, а также в указатели и адреса. Они могут быть сложными, но как только вы получите это, они очень сильны. Я должен сказать, однако, я никогда не использовал 'scanf' (или его братьев и сестер) в реальном проекте. –

0

For A:

(A) int i=0; scanf("%d", i); 

Это должно быть:

(A) int i=0; scanf("%d", &i); 

Возьмите взгляд на signature из scanf()

1

Узнайте это:

int i = 0; scanf ("% d", i);

Expanation: какой адрес переменной i? для этого & оператор дает адрес переменной i. scanf() получает пользовательский ввод и сохраняет значения на этом адресе.

char * s = "1234567"; scanf ("% 3s", & s);

Пояснение: В этом случае вы назначали строку символьному указателю и находились в разделе кода. Основная цель этого варианта - мы не можем изменить раздел кода. Но в этом случае мы модифицируем указатель. поэтому после этого указатель указывает на вновь назначенный адрес, иначе он может ввести неправильный адрес, а затем получить ошибку сегментации. поэтому мы потеряли ранее назначенную строку.

+1

Неверно на втором месте. Посмотрите ближе на вызов 'scanf'. – paddy

+1

Да. ты был прав. На самом деле, есть адрес указателя. –

2

Вы должны передать указатель на функцию, чтобы он знал, где в памяти хранить значение. Если вы просто пройдете по значению, он будет рассматривать это как адрес памяти, и весь ад разрывается. Поэтому вы используете &, чтобы взять ссылку (т. Е. Адрес памяти) вашей переменной.

Именно поэтому A и D являются неправильными.

Что касается C, он выглядит правильно, потому что вы поставляете указатель, но вы на самом деле ссылки на этот указатель. Таким образом, scanf будет писать поверх самого указателя, а не на память, на которую он указывает.

Если вы только что поставили s, тогда мы попадаем в другую землю без земли. Указатель представляет собой строковый литерал , который вы не можете изменять. Однако, если это не было буквальным, но массив с помощью литерала как инициализаторе он бы будет хорошо, если вы не читали в больше данных, чем он может хранить:

char s[] = "1234567"; scanf("%3s", s); /* this is okay */ 
+0

Спасибо! Отличное объяснение для обоих вопросов. Я совершенно не знал (oops ..), что указатель должен был быть как в A, так и в D. – Nuggets10

0

scanf спецификатором как %d принимает вход как адрес места для сканирования.

С 1. Вы даете входные данные как i, что неправильно

С 2. Вы даете входные данные как p, который имеет адрес i .Это устанавливается во время инициализации, как int *p=&i. Так что это правильно.

С 3. спецификатором является %s. Это берет ввод адреса, на котором начинается запись строки. Вход s является массивом и уже содержит адрес. &s ошибочно.

С 4. Вы используете спецификатор %c, который также берет адрес местонахождения. Таким образом, ввод c является неправильным в этом случае, поскольку для получения нужного вам адреса &c

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