跳转到内容

软件工程师手册/语言词典/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;)。
华夏公益教科书