logo search
Языки программирования

4.8. Операторы присваивания

Смысл оператора присваивания:

переменная := выражение;

состоит в том, что значение выражения должно быть помещено по адресу па­мяти, обозначенному как переменная. Обратите внимание, что левая часть оператора также может быть выражением, если это выражение можно вычис­лить как адрес:

Ada

a(i*(j+1)):=a(i*j);

Выражение, которое может появиться в левой части оператора присваивания, называется l-значением; константа, конечно, не является 1-значением. Все вы­ражения дают значение и поэтому могут появиться в правой части оператора присваивания; они называются r-значениями. В языке обычно не определяет­ся порядок вычисления выражений слева и справа от знака присваивания. Ес­ли порядок влияет на результат, программа не будет переносимой.

В языке С само присваивание определено как выражение. Значение конструкции

переменная = выражение;

такое же, как значение выражения в правой части. Таким образом,

C


int v1 , v2, v3;

v1 = v2 = v3 = e;

означает присвоить (значение) е переменной v3, затем присвоить результат переменной v2, затем присвоить результат переменной v1 и игнорировать ко­нечный результат.

В Ada присваивание является оператором, а не выражением, и многократ­ные присваивания не допускаются. Многократное объявление

V1.V2.V3: Integer :=Е;

рассматривается как сокращенная запись для

Ada

V1 : Integer :=E;

V2: Integer := Е;

V3: Integer := Е;

а не как многократное присваивание.

Хотя стиль программирования языка С использует тот факт, что присваи­вание является выражением, этого, вероятно, следует избегать как источник скрытых ошибок программирования. Весьма распространенный класс оши­бок вызван тем, что присваивание («=») путают с операцией равенства («==»). В следующем операторе:

C

If (i=j)...

программист, возможно, хотел просто сравнить i и j, не обратив внимания, что значение i изменяется оператором присваивания. Некоторые С-компиляторы расценивают это как столь плохой стиль программирования, что выдают пре­дупреждающее сообщение.

Полезным свойством языка С является комбинация операции и присваи­вания:

C


v+=e; /* Это краткая запись для... */

v = v + е; /* такого оператора. */

Операции с присваиванием особенно важны в случае сложной переменной, включающей индексацию массива и т.д. Комбинированная операция не толь­ко экономит время набора на клавиатуре, но и позволяет избежать ошибки, если v написано не одинаково с обеих сторон от знака «=». И все же комбинированные присваивания — всего лишь стилистический прием, так как оптимизирующий компилятор может удалить второе вычисление адреса v.

Можно предотвратить присваивание значения объекту, объявляя его как константу.

const int N = 8; /* Константа в языке С */

N: constant Integer := 8; — Константа в языке Ada

Очевидно, константе должно быть присвоено начальное значение.

Есть различие между константой и статическим значением (static value), которое известно на этапе компиляции:

procedure P(C: Character) is

С1 : constant Character := С;

Ada

С2: constant Character :='х';

Begin

case C is

when C1 => -- Ошибка, не статическое значение

when C2 => -- Правильно, статическое значение

end case;

end P;

Локальная переменная С1 — это постоянный объект, в том смысле что значе­ние не может быть изменено внутри процедуры, даже если ее значение будет разным при каждом вызове процедуры. С другой стороны, варианты выбора в case должны быть известны во время компиляции. В отличие от языка С язык C++ рассматривает константы как статические:

C++

const int N = 8;

int a[N]; //Правильно в C++, но не в С

Реализация

После того как вычислено выражение в правой части присваивания, чтобы сохранить его значение в памяти, нужна как минимум одна команда. Если вы­ражение в левой части сложное (индексация массива и т.д.), то понадобятся дополнительные команды для вычисления нужного адреса памяти.

Если длина значения правой части превышает одно слово, потребуется не­сколько команд, чтобы сохранить значение в случае, когда компьютер не под­держивает операцию блочного копирования, которая позволяет копировать по­следовательность заданных слов памяти, указав начальный адрес источника, начальный адрес приемника и число копируемых слов.