分类:
2011-06-24 14:15:28
众所周知RPGLE有3种传参方式,分别是by reference, by value, by read-only reference
下面就这三种传参方式,结合red book来谈谈自己的理解。
一By reference
RPGLE默认的传参方式就是by reference。用CALL/PLIST来调用程序就是典型的by reference方式。
By reference原理:
By reference方式实际上是把变量的指针传给被调用的程序,被调用的程序可以修改变量指针所指向的值,然后把变量的指针返回给调用者,这样调用者就可以使用被修改过的变量了。
By reference有两点注意事项:
1.调用*PGM类型的程序,只能使用By reference(by read-only reference)。
2.调用external program call (EXTPGM)也只能用By reference(by read-only reference)。
二By value
对于使用原型定义的procedure(prototyped procedure),除了使用by reference外,还可以使用by value的方式传参。
By value 顾名思义,是把变量值传递给被调用者,注意仅仅是变量所代表的值,而非变量本身。变量本身不发生任何变化。
实际上,用by value方式,被调用者也可以改变变量值,但是这个改变仅仅发生在被调用的程序范围内。即这种变化对于调用者来说,是不可见的,是透明的。
By value实现原理:
Red book并没有给出by value方式的实现原理(我没找到,anyone knows?),但是我根据by read-only reference方式实现的原理,猜测by value的原理,大概应该如下:
当用by value传参数时,编译器会把这个参数拷贝到一个临时变量中,然后把这个临时变量的指针传递给被调用的程序。这样的话,无论被调用的程序对此参数做如何操作,都不会影响原来的参数值,因为他改变的仅仅是临时变量的值。所以用by value方式传参,不会改变原变量的值。
By value的定义方法(key word:value):
D function1 PR
D parm1
By value的优势有哪些呢?
1.它可以使用字符、数字常量和表达式作为参数传递。
2.它可以弱化数据类型的检查匹配。比如你定义个参数 5P 0,你传给它3S 1也是可以的。
3.你也可以像by reference那样用变量作为参数传递,但是从调用者的角度来看,这个变量值是不会被改变的(参见by value原理)
三 by read-only reference
第三种方式比较有意思,因为他是by reference和by value的合体,兼有两种方式的优点。
首先,by read-only reference从字面上来看,它是也是by reference方式,所以适用by reference的地方,也都适用by read-only reference。只不过它前面加了一个限定词read-only,即只读,却不能改变,那么它又具备了by value的特点,这样by value的各种优势他也具备了。
By read-only reference的定义方法(key word:const):
D function2 PR
D parm2
By read-only reference的注意事项:
用by read-only reference传参,要确保这个参数值在被调用的程序中不会被修改,即这个参数是input parameter(有点类似于F-spec定义文件的打开方式,by read-only reference必须用IF的方式打开,不能用UF的方式打开,即read-only parameter不能被修改)。如果被调用的程序会修改input parameter的值,那么放心好了,程序也不会出现任何问题。因为编译就没法通过……
By read-only reference的优点:
参见by value
By read-only reference的原理:
参见by value
四 如何合理的选择各种参数传递的方式
以上三种传参方式各有各的好处。有的情况下3种方式都可以使用,有的情况下只能使用特定的某种方式。从下表可以看出:(文字有点啰嗦,看图一目了然)
1.调用program只能用by reference的方式。(CALL /CALLP EXTPGM)
2调用没有定义原型的procedure,也只能用by reference的方式。(CALLB)
3.by value只能用于调用procedure。(CALLP EXTPROC/EXPRESSION)
4 by reference 适用于所有的CALL 方式。
5有定义原型的procedure,三种传参方式都适用。
|
CALL |
CALLB |
CALLP EXTPGM |
CALLP EXPPROC |
EXPRESSION |
By reference |
O |
O |
O |
O |
O |
By value |
|
|
|
O |
O |
至于by read-only reference的使用,如果必须用by reference的方式传参,并且你能保证被调用的程序不会更改这个参数值,那么就可以使用by read-only reference了。
关于by value 和by read-only reference应该选那一个,按照red book的说法:
1.如果参数是数字型或者指针型的,那么使用by value在效率上会稍稍高一点。
2.其他的情况,请选择by read-only reference。