按值/结果调用(也称为复制/恢复)

时间:2011-03-08 10:05:56

标签: parameters programming-languages parameter-passing

我正在阅读我的编程语言书籍,学习有关参数传递的一些事情,并且有人怀疑与价值/恢复呼叫有关。

我理解它在一般情况下是如何工作的,但请考虑这种情况:

procedure P(x, y, i){
    x[i]=y[5-i]
    if( i<4 ) P(x, y, i+1)    
}

procedure main(){
    a=(1, 2, 3, 4, 5)
    P(a, a, 0)
}

一旦调用P(a,a,0),就会创建两个'a'的本地副本(让我们称之为a_0和a_1)。但是当它返回时,a_0和a_1将具有不同的值。

a_0 = (5, 4, 3, 2, 5)
a_1 = (1, 2, 3, 4, 5)

因此,当它试图用新值恢复'a'时,我们发现了两种不同的可能性。这会发生什么?它会首先恢复到a_0并被a_1覆盖吗? P(a,a,0)之后'a'的值是多少?

抱歉错误的标签,但我尝试使用“参数”之类的东西,但我还不允许创建新标签。

提前致谢。

2 个答案:

答案 0 :(得分:3)

在这种情况下,有三种可能的方法来定义语义:

  • 禁止此类陈述。编译器静态检查并防止此类情况。这可能很难实现,参数是通过一系列过程调用传递的。

  • 语义是其中一个副本优先于另一个副本。这可以通过逐个恢复每个参数值来实现。两个引用相同原始变量的事实意味着该变量中有两个副本,后者将成功。

  • 语义未定义,每个编译器都可以根据需要自由实现。 C对于过程参数的评估顺序具有这样的语义。在这种情况下,程序员需要注意这一点,以避免编写不可移植的代码。

因此实际的语义将取决于您正在考虑的语言/编译器组合。另一方面,如果提供了编程语言的明确的形式语义(并且已经证明某些属性,例如它是明确的),那么检查语义是确定程序结果应该是什么的方式。

有趣的问题是,call-by-copy-restore的形式语义是什么样的。

答案 1 :(得分:0)

完全取决于您使用的特定语言的规则。你的例子看起来像伪代码,而不是任何真正的语言;所以答案可以是你喜欢的任何东西。 ;)

我所知道的唯一使用call-by-copy的真正语言是Fortran。我不是Fortran专家,但Fortran-2008标准似乎表明你的例子是非法的 - 如果你在Fortran中尝试它,编译器可以做任何它喜欢的事情。

  

如果有效之间存在部分或完全重叠   同一程序和两个不同虚拟参数的参数   伪参数既没有POINTER也没有TARGET属性   重叠部分不得定义,重新定义或成为   在执行过程期间未定义。例如,在

CALL SUB (A (1:5), A (3:9))
     

A(3:5)不得通过定义,重新定义或未定义   第一个伪参数,因为它是相关参数的一部分   使用第二个伪参数,不得定义,重新定义或   通过第二个伪参数变得不确定,因为它是一部分   与第一个伪参数关联的参数。 A(1:2)   通过第一个伪参数仍然可以定义,A(6:9)仍然存在   可以通过第二个伪论证来定义。
ISO/IEC 1539–1:2010 (E),p。 301,注12.34

在实践中,我相信所有现代Fortran编译器都使用call-by-reference而不是逐个拷贝,因此问题永远不会出现。

在Objective-C(obscure circumstances)中引用了副本,但该语言没有标准或规范;它只是由今年编译器所做的定义。它的当前规则似乎是将值复制回实际参数,因为它们从左到右显示在参数列表中,因此a的最终值将是y的值,而不是x的价值。例如:

cat >pass-by-copy.m <<EOF
#import <Foundation/Foundation.h>

void sub(NSString **x, NSString **y) {
    *y = @"bar";
    *x = @"baz";
}

int main() {
    NSString *a = @"foo";
    sub(&a,&a);  // looks like call-by-reference, is actually call-by-copy
    NSLog(@"%@\n", a);  // prints "bar", not "baz"
}
EOF
clang -fobjc-arc -framework Foundation pass-by-copy.m -o pass-by-copy
./pass-by-copy

2012-09-02 22:37:26.677 pass-by-copy[72719:707] bar