Функция scanf
должна получить доступ к объекту , в который читается значение.Все аргументы функции C передаются по значению, поэтому, если вы напишите
int a, b;
scanf("%d%d", a, b); // THIS IS WRONG
, функция scanf
сможет видеть только значения a
и b
, какими они были, когда функция быланазывается.Он не сможет изменить a
.
. Для присвоения в качестве левого операнда требуется lvalue .Lvalue (для упрощения) - это выражение, обозначающее объект;имя переменной является наиболее распространенным видом lvalue.Поскольку оператор присваивания =
встроен в язык, он может иметь специальные правила, применимые к нему.В частности, lvalue на LHS =
идентифицирует объект, которому назначается;это не дает (предыдущее) значение этого объекта.Вот как назначение определяется языком.
Например, если вы напишите:
a = b;
оба a
и b
являются lvalues, но они обрабатываются по-разному из-заих контекст.a
относится к объекту, имя которого a
.b
также относится к объекту, но в этом контексте он возвращает текущее значение этого объекта.
Если бы назначение было реализовано как вызов функции, ему нужно было бы взять адрес объекта, которому назначается:
int assign(int *lhs, int rhs);
assign(&a, b);
Для языка может требоваться адрес для LHS назначения, но гораздо проще использовать имя только целевого объекта.
(Чтобы пояснить упрощение, приведенное выше, определение lvalue в текущем стандарте является «выражением (с типом объекта, отличным от void), которое потенциально обозначает объект». Слово «потенциально» существует потому, что, например,, *ptr
, где ptr
- указатель, является lvalue, даже если текущее значение ptr
равно NULL
. Быть lvalue является концепцией времени компиляции. Попытка присвоить значение *ptr
допустима,но имеет неопределенное поведение.)