Intereting Posts
Как написать в конкретную строку файла в c? При привязке клиентского TCP-сокета к конкретному локальному порту с Winsock SO_REUSEADDR не имеет никакого эффекта Правильный способ использования scanf / printf (и семейства) с фиксированными размерами? Почему объявление внешней переменной внутри main () работает, но не определяет ее внутри main ()? Стандарт Misra для встроенного программного обеспечения Преобразование с шестнадцатиричным преобразованием в десятичное число Почему число чисел с плавающей запятой составляет 7 или 6 получить последний токен строки в C использование бесплатных для хоста результатов в результате сегментации Проверьте, является ли файл конкретным типом в C хранить известные пары ключ / значение в c Что такое привилегированное обучение? .dSYM-файлы, созданные из командной строки (Mac) Как использовать структуру? распечатать на экране с приложения-консоли c, переписывающего текущую строку

Поведение scanf ()

Возможный дубликат:
путаница в scanf () с & operator

Зачем нам нужен & in scanf для ввода целого числа и почему не для символов. Изначально & in scanf ссылается на точное расположение при вводе.

Например:-

main() { int a; char c; scanf("%d",&a); scanf("%c"c); } 

Для каждого спецификатора преобразования scanf() ожидает, что соответствующий аргумент будет указателем на соответствующий тип: %d ожидает аргумент типа int * , %f ожидает аргумент типа double * , %c и %s оба ожидают аргумент типа char * и т. д.

Разница между %c и %s заключается в том, что первая сообщает scanf() чтобы прочитать один символ и сохранить его в местоположении, указанном соответствующим аргументом, в то время как последний сообщает scanf() читать несколько символов, пока не увидит 0- значный символ и сохранить все эти символы в буфере, начиная с места, указанного аргументом.

Вы должны использовать оператор & для своих аргументов, если они еще не имеют тип указателя. Например:

 int x; int *px = some_valid_memory_location_such_as_&x; char c; char *pc = some_valid_memory_location_such_as_&c; ... scanf("%d", &x); // x is not a pointer type, so we must use the & operator scanf("%d", px); // px is a pointer type, so we don't need the & operator scanf("%c", &c); // etc. scanf("%c", pc); // etc. 

Там, где вещи запутываются, это чтение строк символов (с использованием спецификатора преобразования %s ):

 char buf[SIZE]; scanf("%s", buf); // expression 'buf' *implicitly* converted to pointer type 

Почему нам не нужен оператор & в этом случае? Это связано с тем, как C обрабатывает выражения массива. Когда компилятор видит выражение типа массива (например, buf в вызове scanf() ), он будет неявно преобразовывать выражение из N-element array of T типа N-element array of T типа N-element array of T в pointer to T и устанавливать его значение в адрес первого элемент в массиве. Это значение не является значением lvalue – его нельзя назначить (поэтому вы не можете написать что-то вроде buf = foo ). Единственные исключения из этого правила – это когда выражение массива является операндом операторов sizeof или & или выражение массива является строковым литералом, используемым для инициализации другого массива:

 char *p = "This is a test"; // string literal implicitly converted to char *, // string *address* written to p char a[] = "This is a test"; // string literal not implicitly converted, // string *contents* copied to a 

Короче говоря, выражение buf неявно преобразуется из типа char [SIZE] в char * , поэтому нам не нужно использовать оператор & , и на самом деле тип выражения &buf был бы pointer to SIZE-element array of char , или (*)[SIZE] , что не соответствует scanf() для спецификатора преобразования %s .

Символ амперсанда требуется в обоих случаях. scanf требует указателей (вы, вероятно, думали о char * или char [] – они сами указатели).

Scanf считывает ввод в адрес памяти. a – значение, принадлежащее a. &a – местоположение a в памяти.

В вашем коде выше c должен быть &c .

Поскольку scanf() нуждается в указателях, а &a – указатель на целое число.

В вашем примере вам нужна запятая и амперсанд перед c .

 int main(void) { int a; char c; char s[21]; scanf("%d",&a); scanf("%c", &c); // Fixed! scanf("%20s", s); printf("a = %d, c = %c, s = <<%s>>\n", a, c, s); } 

Если вы читали строку, вы передавали бы строку – указатель на char – для scanf() .

Вам нужно указать scanf с указателем, поэтому у вас есть & in scanf («% d», & a) ; , scanf (“% c” c) ; не будет работать вообще.

Ваш пример неправильный. Если у тебя есть

 char c; 

то вам нужно добавить & к имени при вызове scanf :

 scanf("%c", &c); 

Однако , если ваша переменная уже является указателем, например, потому что это char[] (который является причудливым синтаксисом для указателей), вы должны опустить & .

Мне нравится думать об амперсанде (&) как о «адресе». Итак, вы читали &a как «адрес».

Кроме того, я попытался скомпилировать это, но он предупредил меня о gcc:

 Warning: format "%c" expects type 'char *', but argument 2 has type 'int' 

Это верно, поскольку char в основном является int.