跳轉到內容

軟體工程師手冊/語言詞典/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;)。
華夏公益教科書