按引用调用和按值调用结果

Sru*_*mha 2 pascal pass-by-reference call-by-value

好吧,我和我的朋友就下面的代码进行了辩论。我们对它产生的输出有点困惑。有人可以澄清以下代码段的按引用调用和按值调用结果吗?

program params;
    var i: integer;
    a: array[1..2] of integer;

    procedure p(x,y: integer);
    begin
        x := x + 1;
        i := i + 1;
        y := y + 1;
    end;

begin
    a[1] := 1;
    a[2] := 2;
    i := 1;
    p( a[i],a[i] );
    output( a[1],a[2] );
end.
Run Code Online (Sandbox Code Playgroud)

在参数通过 value-result 和通过引用传输到过程 p 的情况下,该程序的结果输出。

Ren*_*nzo 5

按价值调用

xyinp是用实参初始化的局部变量,whilei是全局变量,所以调用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 */
Run Code Online (Sandbox Code Playgroud)

最后打印值 1, 2,因为它们是 的值a[1]a[2]未更改。

参考调用

双方xyp有别名a[1]和(再次)a[1](因为i = 1当程序被调用),所以调用等效于:

a[1] := 2  /* a[1] + 1 */
i    := 2  /* i + 1 */
a[1] := 3  /* a[1] + 1 */
Run Code Online (Sandbox Code Playgroud)

最后打印值 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 */
Run Code Online (Sandbox Code Playgroud)

最后打印值 2, 3。在实践中,实现调用匿名函数(“thunk”),每次它必须评估一个参数。

按值调用结果

只是为了完成讨论,这里是值-结果参数传递的情况,其中xy在程序执行开始时使用实际参数的值进行初始化,并且在程序执行结束时,被复制回原始变量地址

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]!) */
Run Code Online (Sandbox Code Playgroud)

最后打印值 2, 2。

有关传递参数的不同方式的讨论,请参见例如this