Подтвердить что ты не робот

Что произойдет, если '&' не будет введен в 'scanf' в C?

Я отправился на собеседование, в котором меня задали вопрос:

Что вы думаете о следующем?

int i;
scanf ("%d", i);
printf ("i: %d\n", i);

Я ответил:

  • Программа будет успешно скомпилирована.
  • Он напечатает номер неправильно, но он будет работать до конца без сбоев

Ответ, который я сделал, был неправильным. Я был ошеломлен.

После этого они уволили меня:

В некоторых случаях программа выйдет из строя и приведет к дампу ядра.

Я не мог понять, почему программа потерпит крах? Может ли кто-нибудь объяснить мне причину. Любая помощь была оценена.

4b9b3361

Ответ 1

Когда переменная определена, компилятор выделяет память для этой переменной.

int i;  // The compiler will allocate sizeof(int) bytes for i

i, определенный выше, не инициализирован и имеет неопределенное значение.

Чтобы записать данные в эту ячейку памяти, выделенную для i, вам необходимо указать адрес переменной. Утверждение

scanf("%d", &i);

будет записывать данные int пользователем в ячейку памяти, выделенную для i.

Если & не помещается перед i, тогда scanf попытается записать входные данные в ячейку памяти i вместо &i. Поскольку i содержит неопределенное значение, существуют некоторые возможности, которые могут содержать значение, эквивалентное значению адреса памяти, или оно может содержать значение, выходящее за пределы адреса памяти.

В любом случае программа может вести себя беспорядочно и приведет к поведению undefined. В этом случае все может случиться.

Ответ 2

Beacuse вызывает поведение undefined. Семейство функций scanf() ожидает указатель на целое число, когда найден спецификатор "%d". Вы передаете целое число, которое можно интерпретировать как адрес некоторого целого числа, но это не так. Это не имеет определенного поведения в стандарте. Он действительно скомпилируется (однако, будет выдано какое-то предупреждение), но это, безусловно, будет работать неожиданным образом.

В коде как есть, есть еще одна проблема. Переменная i никогда не инициализируется, поэтому она будет иметь неопределенное значение, а еще одна причина для undefined Поведение.

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

Ответ 3

Вы передали данные с неправильным типом (ожидается int*, но int) до scanf(). Это приведет к поведению undefined.

Все что может случиться для поведения undefined. Программа может вылететь из строя и может не сработать.

В типичной среде я предполагаю, что программа выйдет из строя, когда какой-то "адрес", указывающий на место, которое не разрешено записывать в операционную систему, передается в scanf(), и запись на него будет иметь OS завершает прикладную программу, и это будет наблюдаться как сбой.

Ответ 4

Одна вещь, о которой другие ответы еще не упоминались, заключается в том, что на некоторых платформах sizeof (int) != sizeof (int*). Если аргументы переданы определенным образом *, scanf может сожрать часть другой переменной или адрес возврата. Изменение адреса возврата может привести к уязвимости безопасности.

* Я не специалист по ассемблеру, поэтому возьмите это с солью.

Ответ 5

Я не мог понять, почему программа потерпит крах? Может ли кто-нибудь объяснить мне причину. Любая помощь была оценена.

Возможно, еще немного применено:

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

С помощью первой команды вы выделяете память для одного целочисленного значения и записываете 123 в этот блок памяти. В этом примере предположим, что этот блок памяти имеет адрес 0x0000ffff. С помощью второй команды вы читаете свой ввод, а scanf записывает вход в блок памяти 0x0000ffff - потому что вы не получаете доступ (разыменовываете) значение этой переменной i, а адресуете.

Если вы используете команду scanf ("%d", i);, вместо этого вы записываете ввод в память адрес 123 (потому что это значение хранится внутри этой переменной). Очевидно, что это может пойти ужасно неправильно и вызвать крушение.