软件工程师手册/语言词典/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;)。