2016-03-11 3 views
2

В C, когда & отсутствует для аргумента в scanf(), не возникает ошибка компиляции; вместо этого отображаемые результаты неверны (т. е. возникает семантическая ошибка).Отсутствие спецификатора доступа и в C не приводит к ошибке компиляции

Рассмотрим следующий код:

char str[30]; 
int a; 
printf("Enter the value"); 
scanf("%s %d", str, a);  // This is the statement in question. 
printf("You entered %s %d", str, a); 

Здесь я знаю str является массив символов, так что будет иметь базовый адрес, и, таким образом, не будет производить ошибку компиляции. Но почему отсутствие & для аргумента a не приводит к ошибке компиляции?

Также str дает правильный выход, но целое число всегда производит значение -28770 как выход. Почему это?

+0

Что вы вводите? И что вы ожидаете от вывода? –

+0

"целое число, всегда указывающее -28770 как результат" - неинициализированная локальная переменная 'a'. Содержит все, что было в этой ячейке памяти (стек или регистр) до объявления. Может быть одинаковым при каждом прогоне, каждый раз может быть разным; поэтому это «неопределенное поведение». - Разве ваш компилятор не предупредил вас об этом? – JimmyB

+0

в порядке. И компилятор не дал никаких предупреждений. Спасибо за ответ. – Gon

ответ

2
int scanf(const char *format, ...); 

Это прототип scanf. Первый аргумент - char *, а другие аргументы - переменные длины. Таким образом, никакая ошибка не будет сгенерирована.

+0

Чтобы разработать: varargs в 'scanf()' не имеют объявленного типа и, следовательно, для компилятора может быть абсолютно любым. – JimmyB

1

Как писал Umamahesh P, вы не получите ошибку компиляции, так как scanf является переменной аргументом. Что касается того, что происходит при запуске программы, это то, что стандарт C вызывает «неопределенное поведение». Все может случиться. Вам нужно посмотреть, что происходит на машинной инструкции и на уровне адресной памяти, чтобы узнать, что именно делает scanf с целым значением, которое вы дали ему вместо указателя.

+0

Не будет 'scanf (..., a)' даже попробовать и записать введенное значение в случайное местоположение в памяти, вероятно, segfault? – JimmyB

+0

@HannoBinder, который может произойти, но поведение _undefined_, что означает, что все может произойти. – davmac

+1

@ HannoBinder: Как писал davmac, это может случиться, но никаких гарантий нет.Другое поведение, которое я видел, это то, что аргументы передаются в регистры, а 32-разрядные целые числа и 64-разрядные указатели передаются в разных регистрах, поэтому scanf получает указатель на что-то, что оказалось в правом регистре. –

4

scanf имеет прототип:

int scanf(const char *fmt, ...); 

... означает, что любое количество аргументов любого типа может быть уточнена после fmt. Следовательно, вызывающий, а не компилятор, несет ответственность за обеспечение того, чтобы предоставленные аргументы соответствовали ожидаемой функции.

0

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

Также, если он пытается показать эти предупреждения, ваш компилятор будет полностью неспособен сделать это, если вы используете vscanf() или используете динамическую строку в качестве параметра формата.

Например, это выход я получаю с помощью MinGW-64 GCC 4.5.4:

gcc -Wall -o small.exe small.c 

small.c:7:3: warning: format '%d' expects type 'int *', but argument 3 has type 'int' 
small.c:7:8: warning: 'a' is used uninitialized in this function 

Просто добавьте -Werror возможность включить эти предупреждения в ошибки.

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

  • Нет связанных вопросов^_^