サブルーチンの使い方
サブルーチンの使い方についてRPGとCを比較して見ましょう!
RPGでのサブルーチンの使用法は以下の通りです。
H Y/ 1
H*---------------------------------------------------------------*
H* PROGRAM-ID : CSPEC1R *
H* REMARKS : サブルーチン *
H* AUTHOR : Y.IDE *
H* DATE-WRITEN : 1999/10/30 *
H* VERSION : 01.00 ORIGINAL *
H*---------------------------------------------------------------*
C* メインルーチン
C EXSR SUB#R1
C EXSR SUB#R2
C SETON LR
C RETRN
C* サブルーチン
C*------------------------------------------------*
C SUB#R1 BEGSR
C*------------------------------------------------*
C 'SUB#R1' DSPLY
C ENDSR
C*------------------------------------------------*
C SUB#R2 BEGSR
C*------------------------------------------------*
C 'SUB#R2' DSPLY
C ENDSR
|
EXSR サブルーチン名
サブルーチン名 BEGSR
ENDSR
サブルーチンの呼出しは EXSR で行いサブルーチンのコードは、
BEGSR 〜 ENDSR の間に記述し、メインルーチンの後ろにおきます。
Cのサブルーチンの使用法は以下の通りです。
/*---------------------------------------------------------------*/
/* PROGRAM-ID : CSPEC1 */
/* REMARKS : C仕様書サブルーチン */
/* AUTHOR : Y.Ide */
/* DATE-WRITEN : 1999/10/30 */
/* VERSION : 01.00 ORIGINAL */
/*---------------------------------------------------------------*/
#include<stdio.h>
#include<stdlib.h>
/* サブルーチン */
void sub_r1(void){
printf(" サブルーチン1 ??/n");
return;
}
/* プロトタイプ */
void sub_r2(void);
/* メインルーチン */
int main(int argc, char *argv[]){
sub_r1();
sub_r2();
exit(0);
}
/* サブルーチン (mainの後ならプロトタイプが必要) */
/*----------------------------------------*/
void sub_r2(void){
/*----------------------------------------*/
printf(" サブルーチン2 ??/n");
return;
}
|
サブルーチンの呼出しは ルーチン名(Cでは通常サブルーチンとは言わず関数と呼びます)で行い
サブルーチンのコードは、{ }の間に記述し、メインルーチンの前におきます。
メインルーチンの後ろに置く場合は(上記 sub_r2 )は、関数の戻り値と引数だけ記述した、
プロトタイプをメインルーチンの前におきます。
プロトタイプがない場合は、コンパイルのときに警告メッセージがでます。
また、RPGの場合は、サブルーチンは必ず同じコードないに記述し、同時にコンパイルすることが必要ですが、
ILEでは、モジュール別に分割して作成することが可能です。
上記の例では、
/* サブルーチン (mainの後ならプロトタイプが必要) */
/*----------------------------------------*/
void sub_r2(void){
/*----------------------------------------*/
printf(" サブルーチン2 ??/n");
return;
}
の部分は、別のモジュールとして作成し、後からバインドすることが可能です。
また、上記のプログラムでは、void sub_r2(void) となっていますが、void というは、
型を持たないということを示します。
つまり、上記は、このサブルーチン(関数)には、引数として渡すパラメータも、戻り値として帰される値もないことを
表しています。
ですから、呼出す場合は、
となります。
もし、int sub_r2(void) となっていた場合には、その呼び出しは、
となるでしょう。(rc は省略しても構いません)
もし、void sub_r2(int) となっていた場合には、その呼び出しは、
となるでしょう。この場合の rc は必須です。
注意が必要なのは、Cの引数は値渡しなので、rc はサブルーチンには渡りますが、呼出しもとのプログラムに
は戻ってきません。
このことは、もしサブルーチン内部で、rc の値を変更したとしても、呼出しもとの rc の値には影響がない(変更が反映しない)ことを意味します。
もし、サブルーチンの変更結果を戻す必要があるのなら、戻り値とする、or 引数をポインターとして定義する or
フィールドの有効範囲(スコープ)を main の外側に出す、ことが必要です。
- 戻り値とする。以下のように記述します。
int main(int argc, char *argv[]){
int rc;
rc = sub_r2();
}
/*----------------------------------------*/
int sub_r2(void){
/*----------------------------------------*/
int rc;
rc = 1;
return rc;
}
- 引数をポインターとして定義する
int main(int argc, char *argv[]){
int rc;
sub_r2(&rc);
}
/*----------------------------------------*/
void sub_r2(int *rc_ptr){
/*----------------------------------------*/
*rc_ptr = 1;
return;
}
ポインターをパラメータとして渡しているので、サブルーチンが変更するのは、main ルーチンのフィールドとなる。
つまり、サブルーチンでの変更が反映することになります。
- フィールドの有効範囲(スコープ)を main の外側に出す
(注)Cでのフィールドは、定義された{}の中でだけで有効です。
{}の外側で定義するとプログラム全体で有効となります。
int rc;
int main(int argc, char *argv[]){
sub_r2();
}
/*----------------------------------------*/
void sub_r2(void){
/*----------------------------------------*/
rc = 1;
return;
}
この例では、rcは main の外側で定義されています、この場合、rc の有効範囲は以降全てのルーチン(関数)に
及びます。
つまり、変更が反映することになります。
OPM−RPGには、内部サブルーチンにパラメーターを渡すことができません。
OPM−RPGには、フィールドの有効範囲がありません。
RPGでのフィールド定義は、プログラムのすべてのルーチンで有効です。
つまり、この例が、OPM−RPGのサブルーチン呼出しに一番近い呼出し方法となります。
|