开发者

Call by value/result (aka copy/restore)

I'm reading my Programming Languages book, learning somethings about parameters passing, and a doubt came to me related to call by value/restore.

I understand how it works in general cases, but consider this case:

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)
}

Once P(a, a, 0) is called, a local copy of both 'a' is created (lets call them a_0 and a_1). But when it returns, a_0 and a_1 will have different values.

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

So when it tries to restore 'a'with the ne开发者_开发问答w value... we find two different posibilities. What would happen here? Would it be first restored to a_0 and the overwritten by a_1? What would be the value of 'a' after P(a, a, 0)?

Sorry for the wrong tag, but I tried to use something like 'parameter' and I'm not allowed to create new tags yet.

Thanks in advance.


In such situations, there are three possible ways to define the semantics:

  • Forbid such statements. The compiler statically checks and prevents such situations. This may be difficult to achieve, is the argument is passed down through a series of procedure calls.

  • The semantics is that one of the copies takes precedence over the other. This would be realised by restoring each of the argument values back one by one. The fact that two refer to the same original variable will mean that there are two copies made into that variable, and the latter will succeed.

  • The semantics are undefined, and each compiler is free to implement this as it sees fit. C has such semantics for the evaluation order of arguments to procedures. In such as circumstances, the programmer needs to be aware of this to avoid writing unportable code.

So the actual semantics will depend on which language/compiler combination you are considering. On the other hand, if unambiguous formal semantics of the programming language are provided (and certain properties have been proven about it, such as that it is unambiguous), then checking the semantics is the way to determine what the result of your program should be.

The interesting question is what do the formal semantics of call-by-copy-restore look like.


It depends completely upon the rules of the particular language you're using. Your example looks like pseudocode, not any real language; so the answer can be whatever you like. ;)

The only real language I know that uses call-by-copy is Fortran. I'm not a Fortran expert, but the Fortran-2008 standard appears to state that your example is simply illegal — if you try it in Fortran, the compiler is allowed to do pretty much whatever it likes.

If there is a partial or complete overlap between the effective arguments of two different dummy arguments of the same procedure and the dummy arguments have neither the POINTER nor TARGET attribute, the overlapped portions shall not be defined, redefined, or become undefined during the execution of the procedure. For example, in

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

A(3:5) shall not be defined, redefined, or become undefined through the first dummy argument because it is part of the argument associated with the second dummy argument and shall not be defined, redefined, or become undefined through the second dummy argument because it is part of the argument associated with the first dummy argument. A(1:2) remains definable through the first dummy argument and A(6:9) remains definable through the second dummy argument.
ISO/IEC 1539–1:2010 (E), p. 301, Note 12.34

In practice, I believe all modern Fortran compilers use call-by-reference instead of call-by-copy, so the problem never comes up.

Call-by-copy is also used under the hood in Objective-C (in obscure circumstances), but that language doesn't have a standard or specification; it's just defined by what the compiler does this year. Its current rule seems to be that the values get copied back into the actual parameters as they appear in the parameter-list from left to right, so that the final value of a would be the value of y, not the value of x. Example:

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜