Вызов по значению
x
и y
в p
— это локальные переменные, инициализированные с фактическими параметрами, а i
— это глобальная переменная, поэтому вызов p( a[i],a[i] )
эквивалентен:
x := 1 /* The value of a[i] */
y := 1 /* The value of a[i] */
x := 2 /* x + 1 */
i := 2 /* i + 1 */
y := 2 /* y + 1 */
и в конце печатаются значения 1, 2, поскольку они являются значениями a[1]
, a[2]
, которые не были изменены.
Вызов по ссылке
И x
, и y
в p
являются псевдонимами для a[1]
и (снова) a[1]
(начиная с i = 1
при вызове процедуры), поэтому вызов эквивалентен:
a[1] := 2 /* a[1] + 1 */
i := 2 /* i + 1 */
a[1] := 3 /* a[1] + 1 */
и в конце печатаются значения 3, 2.
Позвонить по имени
Вызов по имени эквивалентен вызову по ссылке, когда простые переменные передаются в качестве параметров, но отличается, когда вы передаете выражение, обозначающее ячейку памяти, например индекс. В этом случае фактический параметр переоценивается каждый раз, когда он встречается. Итак, в данном случае это эффект вызова p( a[i],a[i] )
:
a[1] := 2 /* since i = 1, the result is equal to a[1] + 1 */
i := 2 /* i + 1 */
a[2] := 3 /* since i is now 2, the result is equal to a[2] + 1 */
и в конце печатаются значения 2, 3. На практике реализация вызывает анонимную функцию («преобразователь») каждый раз, когда она должна оценивать параметр.
Вызов по значению результата
Просто чтобы завершить обсуждение, вот случай передачи параметра значение-результат, в котором x
и y
инициализируются в начале выполнения процедуры значениями фактических параметров, а в конце выполнения процедуры, копируются обратно в исходные переменные адреса:
x := 1 /* The value of a[i] */
y := 1 /* The value of a[i] */
x := 2 /* x + 1 */
i := 2 /* i + 1 */
y := 2 /* y + 1 */
a[1] := 2 /* the value of x is copied back to a[1] */
a[1] := 2 /* the value of y is copied back to a[1] (not a[2]!) */
и в конце печатаются значения 2, 2.
Обсуждение различных способов передачи параметров см., например, в это.
person
Renzo
schedule
26.09.2015