軟體工程師手冊/語言詞典/PLI/儲存類
外觀
注意: 本文需要對 PL/I 的基本瞭解,可以在 軟體工程師手冊/語言詞典/PLI 中找到。
PL/I 提供 4 種不同的儲存類
- 靜態
- 自動 (縮寫:AUTO)
- 受控 (縮寫:CTL)
- 基於
簡化的口語靜態和自動變數將由“機器”分配和初始化,
受控和基於變數必須由“程式(員)”管理。
靜態 變數將在程式啟動時分配和初始化,它們將一直保留在儲存器中直到程式終止[1]。
因此,在程式中宣告的區域性靜態變數在該程式的後續呼叫之間不會丟失其值。
在全域性範圍內宣告的自動變數的行為類似於靜態變數。
在程式中區域性宣告的自動變數將在每次呼叫該程式時分配和初始化,如果該程式終止,它們的儲存將被釋放。
區域性變數預設情況下是自動的[2]。
example: proc options ( main );
call static_memory ( 7 );
call static_memory ( 0 ); /* output: 7 */
call auto_memory ( 7 );
call auto_memory ( 0 ); /* output: 1 */
static_memory: proc ( parm );
dcl parm bin fixed (15);
dcl memory bin fixed (15) init ( 1 ) STATIC;
if parm = 0 then
put skip list ( memory );
else
memory = parm;
end static_memory;
auto_memory: proc ( parm );
dcl parm bin fixed (15);
dcl memory bin fixed (15) init ( 1 );
if parm = 0 then
put skip list ( memory );
else
memory = parm;
end auto_memory;
end example;
如果一個變數被宣告為受控,則該宣告僅描述了該變數的結構,但不會自動進行任何儲存分配。
受控變數的儲存分配必須使用 ALLOCATE 語句 (縮寫:ALLOC)[3] 完成,釋放必須使用 FREE 語句[4] 完成。
受控變數可以分配多次,但只能訪問其當前生成的內容。
example: proc options ( main ); dcl number bin fixed (15) CONTROLLED; ALLOCATE number; /* create the 1st generation of number */ number = 111; put skip list ( number ); /* output: 111 */ ALLOCATE number; /* create the 2nd generation of number */ number = 222; put skip list ( number ); /* output: 222 */ FREE number; /* now 1st generation becomes actual again */ put skip list ( number ); /* output: 111 */ FREE number; /* now the value of number will be undefined */ end example;
在程式中受控的區域性變數在該程式的後續呼叫之間將保持分配狀態。
example: proc options ( main );
call sub_proc ( 333 );
call sub_proc ( - 1 ); /* output: 333 */
sub_proc: proc ( num_val );
dcl num_val bin fixed (15);
dcl num_ctl bin fixed (15) CTL;
if num_val >= 0 then
do;
alloc num_ctl;
num_ctl = num_val;
end;
else
do;
put skip list ( num_ctl );
free num_ctl;
end;
end sub_proc;
end example;
- 受控變數的所有宣告的邊界、長度或大小都可以在分配語句中被覆蓋。
- 在宣告中使用星號表示法強制在第一個分配語句中明確定義。
- 在分配語句中使用星號表示法會繼承當前生成的值。
example: proc options ( main );
dcl stringlist (3) char (10) controlled;
dcl single_string char (*) controlled;
dcl 1 structure controlled,
2 string_1 char (10),
2 string_2 char (10);
dcl allocation builtin;
allocate stringlist; /* 1st generation: 3 strings of length 10 */
allocate stringlist (5); /* 2nd generation: 5 strings of length 10 */
allocate stringlist (5) char (20); /* 3rd generation: 5 strings of length 20 */
allocate stringlist (*) char (*); /* 4th generation: like 3rd generation */
do while ( allocation ( stringlist ) > 0 ); free stringlist; end;
allocate single_string char (50); /* Explicid value must be given because declaration contains asteriks */
free single_string;
allocate structure; /* 1st generation: length ( string_1 ) = length ( string_2 ) = 10 */
allocate 1 structure, /* 2nd generation with ... */
2 string_1 char (70), /* length ( string_1 ) = 70 */
2 string_2 char (80); /* length ( string_2 ) = 80 */
do while ( allocation ( structure ) > 0 ); free structure; end;
end example;
如果一個變數被宣告為基於,則該宣告僅描述了該變數的結構,但不會自動進行任何儲存分配。
- 基於變數的儲存分配可以使用 ALLOCATE 語句 (縮寫:ALLOC)[3] 完成,釋放可以使用 FREE 語句[4] 完成。
- 或者,基於變數可以對映到現有的儲存。
example: proc options ( main ); dcl a_char char (03); dcl b_char char (03) based ( addr ( a_char ) ); dcl c_char char (03) based ( c_pointer ); dcl d_char char (03) based ; dcl x_char char (03) based ( x_pointer ); dcl y_char char (03) based ( y_pointer ); dcl z_char char (03) based ; dcl c_pointer pointer; dcl x_pointer pointer; dcl y_pointer pointer; dcl addr builtin; a_char = 'AAA'; /* now a_char has the value 'AAA' */ b_char = 'BBB'; /* now a_char has the value 'BBB' */ c_pointer = addr ( a_char ); c_char = 'CCC'; /* now a_char has the value 'CCC' */ addr ( a_char ) -> d_char = 'DDD'; /* now a_char has the value 'DDD' */ allocate x_char; /*================================*/ x_char = 'XXX'; /* now x_char has the value 'XXX' */ y_pointer = x_pointer; y_char = 'YYY'; /* now x_char has the value 'YYY' */ addr ( y_char ) -> z_char = 'ZZZ'; /* now x_char has the value 'ZZZ' */ end example;
/* The following procedure gets a char_var variable "string" */
/* as by-reference parameter and trims all spaces from the right. */
/* Structure of a char_var variable: */
/* 2 bytes containing the string length as bin fixed (15) */
/* followed by the characters */
right_trim: proc ( string );
dcl string char (*) varying;
dcl s_length bin fixed (15) based ( addr ( string ) );
dcl s_ch ( - 1 : 32767 ) char (01) based ( addr ( string ) );
do while ( s_ch ( s_length ) = ' ' );
s_length = s_length - 1;
end;
end right_trim;
在以下示例中,ALLOC 語句...
- 為變數 B_VAR 分配儲存
- 將已分配儲存的地址儲存在 B_PTR 中
example: proc options ( main ); dcl B_VAR char (25) BASED ( B_PTR ); dcl B_PTR pointer; ALLOC B_VAR; ............ FREE B_VAR; end example;
基於變數可以分配多次,每個生成都可以透過其單獨的指標直接訪問。
example: proc options ( main );
dcl 1 first_item,
2 value char (01),
2 next pointer init ( null );
dcl 1 last_item like first_item based ( last_ptr );
/* "like" means: last_item has the same structure as first_item */
dcl last_ptr pointer;
dcl ( addr , null ) builtin;
last_ptr = addr ( first_item );
call append_to_simple_list ( '1' );
call append_to_simple_list ( '2' );
call append_to_simple_list ( '3' );
call append_to_simple_list ( '4' );
put skip list ( fifo_of_simple_list ); /* output: '1234' */
call free_simple_list;
append_to_simple_list: proc ( item_value );
dcl item_value char (01);
dcl 1 alloc_item like first_item based ( alloc_ptr );
dcl alloc_ptr pointer;
last_item.value = item_value;
ALLOCATE alloc_item;
last_item.next = alloc_ptr;
last_ptr = alloc_ptr;
last_item.next = null;
end append_to_simple_list;
fifo_of_simple_list: proc returns ( char (20) varying );
dcl list_sum char (20) varying;
dcl 1 read_item like first_item based ( read_ptr );
dcl read_ptr pointer;
list_sum = '';
read_ptr = addr ( first_item );
do while ( read_item.next ¬= null );
list_sum = list_sum || read_item.value;
read_ptr = read_item.next;
end;
return ( list_sum );
end fifo_of_simple_list;
free_simple_list: proc;
dcl 1 free_item like first_item based ( free_ptr );
dcl free_ptr pointer;
dcl next_ptr pointer;
next_ptr = first_item.next;
do while ( next_ptr ¬= null );
free_ptr = next_ptr;
next_ptr = free_item.next;
FREE free_item;
end;
first_item.next = null;
end free_simple_list;
end example;
基於變數可以是自定義結構,即必須在分配語句中定義邊界、長度或大小值的結構。
為了使例如邊界可調整,它在宣告中的固定值必須替換為
expr REFER ( structure_var )
- expr 是一個表示式,它將在分配時計算,並確定儲存值。
- structure_var 是基於結構中的一個變數,它儲存計算後的值。
example: proc options ( main );
dcl 1 based_stru,
2 string_count bin fixed (15),
2 string_length bin fixed (15),
2 list ( alloc_count REFER ( string_count ) )
char ( alloc_length REFER ( string_length ) );
dcl alloc_count bin fixed (15);
dcl alloc_length bin fixed (15);
dcl length builtin;
alloc_count = 5;
alloc_length = 72;
allocate based_stru; /* now list contains 5 strings of length 72 */
put skip list ( based_stru.string_length ); /* output will be 72, the stored calculated value. */
put skip list ( length ( based_stru.list ( 1 ) ) ); /* output will be 72, the length of an allocated string. */
end example;
example: proc options ( main );
dcl 1 based_stru,
2 rows bin fixed (15),
2 columns bin fixed (15),
2 matrix ( alloc_val * 2 REFER ( rows ) ,
alloc_val + 5 REFER ( columns ) )
bin fixed (15);
dcl alloc_val bin fixed (15);
alloc_val = 10;
allocate based_stru; /* now matrix contains 20 rows and 15 columns */
end example;
- [1] 提取程式 中的區域性靜態變數只會在提取語句和釋放語句之間分配。
- [2] 在 PL/I 中,可以使用 DEFAULT 語句更改預設值。
- [3] 受控變數和基於變數都可以在同一個語句中分配 (例如:alloc ctl_var_1 (20), ctl_var_2, based_var;)。
- [4] 受控變數和基於變數都可以在同一個語句中釋放 (例如:free ctl_var_1, ctl_var_2, based_var;)。