scanf () (язык C) сбил меня с толку - PullRequest
6 голосов
/ 17 июня 2010

Когда мне нужно вставить / не вставить & для scanf() в C? Спасибо.

int main()
{
    char s1[81], s2[81], s3[81];

    scanf("%s%s%s", s1, s2, s3);

    // If replace scanf() with the expression below, it works too.
    // scanf("%s%s%s", &s1, &s2, &s3);

    printf("\ns1 = %s\ns2 = %s\ns3 = %s", s1, s2, s3);

    return 0;
}

//programming is fun
//
//s1 = programming
//s2 = is
//s3 = fun

Ответы [ 9 ]

9 голосов
/ 17 июня 2010

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

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

Пример:

char s[81];
int n;
int* nptr;
//Initialize nptr to some meaningful value
scanf("%s %d %d",s,&n,nptr);

В этом случае нам нужно использовать оператор &, чтобы получить адрес, где хранится n. Нам не нужно использовать его с nptr, потому что это уже указатель на какое-то место в памяти, ни с s, потому что массив передается до указателя при передаче в функцию.

6 голосов
/ 17 июня 2010

Аргументы после спецификатора формата должны быть указателями.Когда имя массива передается функции, местоположение исходного элемента передается, поэтому вам вообще не нужно использовать & в вашем примере.Вы можете сделать это, хотя (из K & R ):

int day, year;
char monthname[20];

scanf("%d %s %d", &day, monthname, &year);

Поскольку день и год int, вы должны использовать &, чтобы получитьадрес этих переменных.Поскольку monthname является массивом, & не требуется.

4 голосов
/ 17 июня 2010

В C, когда вы имеете дело с массивами:

int c_array[24];
c_array == &c_array == &c_array[0]

Да, это забавно - они выглядят одинаково (разница в типах). Прочитайте это .

3 голосов
/ 17 июня 2010

Из FAQ по comp.lang.c: Я думал, что вам всегда нужно & для каждой переменной, переданной в scanf.

Я настоятельно рекомендую прочитать остальную часть comp.lang.c FAQ .

2 голосов
/ 17 июня 2010

s1 возвращает адрес первого элемента массива, а &s1 возвращает адрес самого массива. Адрес первого элемента и адрес самого массива идентичны, поэтому оба представления работают.

1 голос
/ 17 июня 2010

Scanf принимает переменное количество параметров. Первый аргумент scanf - это формат, а после этого n указывает, где хранятся значения, а n - номер формата, указанный в строке формата. поскольку вы используете массив, для хранения значений необходимо указать базовый адрес массива.


//If int
int i;
scanf("%d",&i); // store int value at address &i

float f;
scanf("%f",&f); //store float value at address &f

int a[10];
scanf("%s",a); //store string or array value at a

Если использование последней строки смущает вас, вы можете попробовать то же самое с адресом первого элемента, который является & a [0].

Надеюсь, это поможет,
GG

1 голос
/ 17 июня 2010

Если a является массивом, оба значения a и &a приводят к указателю в этом контексте:

  • a происходит из-за того, что массив распадается на указатель (C99, §6.3.2.1 / 3 ):

    За исключением случаев, когда это операнд оператора sizeof или унарный оператор & или строковый литерал, используемый для инициализации массива, выражение, имеющее тип '' массив типа ' 'преобразуется в выражение с типом' 'указатель на тип' ', которое указывает на начальный элемент объекта массива и не является lvalue.

    ... выделение добавлено

  • &a делает в результате действия оператора & - возвращает указатель на объект.

1 голос
/ 17 июня 2010

Просто предположение, но я бы предположил, что это потому, что s1, s2 и s3 являются массивами.

0 голосов
/ 17 июня 2010

Как правило, вы будете использовать scanf так же, как и в своей строке без комментариев.Способ работы массивов C - это имя таких массивов, как s1, s2 и s3, на самом деле это адрес первого элемента массива.Для любых примитивов вы должны использовать синтаксис & variable.Например:

float f;
scanf("%f", &f);
...