第7章  I仕様書−データストラクチャー
RPGプログラマーの為のC言語講座

データストラクチャーの違いについてみて行きましょう。

下記のRPGでは、データストラクチャーDATASを定義しています。

     H            Y/                                    1
     H*---------------------------------------------------------------*
     H* PROGRAM-ID    :    ISPEC2R                                    *
     H* REMARKS       :    データストラクチャー                 *
     H* AUTHOR        :    Y.IDE                                      *
     H* DATE-WRITEN   :    1999/8/15                                  *
     H* VERSION       :    01.00 ORIGINAL                             *
     H*---------------------------------------------------------------*
     IDATAS       DS
     I                                    B   1   40B1
     I                                    B   5   60B2
     I                                    B   7  100B3
     I                                       11  11 C1
     I                                       12  12 C2
     I                                       13  22 STR
     C*
     C                     Z-ADD1         B1
     C                     Z-ADD2         B2
     C                     Z-ADD3         B3
     C                     MOVE 'A'       C1
     C                     MOVE 'B'       C2
     C                     MOVEL'STRING  'STR
     C*
     C                     CALL 'ISPEC2'
     C                     PARM           DATAS
     C*
     C                     SETON                     LR
     C                     RETRN
     C*

このデータストラクチャーは、

4byte+2byte+4byte+1byte+1byte+10byte=22byte

のデータストラクチャーです

そして、このデータストラクチャーDATASをパメーターとして、Cを呼び出しています。

下記のCでは、データストラクチャーONEとTWOを定義しています。それぞれのサブフィールドは同じにしてあります。

ONEとTWOの違いは、TWOの方には_Packedを定義してあり、ONEにはありません。

/*---------------------------------------------------------------*/
/* PROGRAM-ID  : ISPEC2                                          */
/* REMARKS     : I仕様書データストラクチャー                    */
/* AUTHOR      : Y.Ide                                           */
/* DATE-WRITEN : 1999/8/15                                       */
/* VERSION     : 01.00 ORIGINAL                                  */
/*---------------------------------------------------------------*/
/* データストラクチャー                                          */
/* RPG C のデータストラクチャーの受渡し                          */
/* バウンダリーについて理解すること                              */
/* AS/400の場合は 4 バイトの境界合わせとなる               */

#include<stdio.h>

typedef struct Data_Struct_One
    {
       int  b1;            /* 4 byte */
       short int  b2;      /* 2 byte */
       int  b3;            /* 4 byte */
       char c1;            /* 1 byte */
       char c2;            /* 1 byte */
       char str[10];       /* 10 byte */
    } Data_Struct_One_t;

typedef _Packed struct Data_Struct_Two
    {
       int  b1;            /* 4 byte */
       short int  b2;      /* 2 byte */
       int  b3;            /* 4 byte */
       char c1;            /* 1 byte */
       char c2;            /* 1 byte */
       char str[10];       /* 10 byte */
    } Data_Struct_Two_t;

void main(int argc, char *argv[]){
  Data_Struct_One_t *ONE;
  Data_Struct_Two_t *TWO;

  /*パラメーター取得*/
  ONE = (Data_Struct_One_t *)argv[1];
  TWO = (Data_Struct_Two_t *)argv[1];

  printf("******** Packedしてないデータストラクト********\n");
  printf("B1 = %d \n",ONE->b1);
  printf("B2 = %d \n",ONE->b2);
  printf("B3 = %d \n",ONE->b3);
  printf("B3 HEX = %x \n",ONE->b3);
  printf("C1 = %c \n",ONE->c1);
  printf("C2 = %c \n",ONE->c2);
  printf("STR = %s \n",ONE->str);

  printf("******** Packedしたデータストラクト********\n");
  printf("B1 = %d \n",TWO->b1);
  printf("B2 = %d \n",TWO->b2);
  printf("B3 = %d \n",TWO->b3);
  printf("C1 = %c \n",TWO->c1);
  printf("C2 = %c \n",TWO->c2);
  printf("STR = %s \n",TWO->str);

}

この結果、ONEは正常に表示できず、B3フィールド移行がずれてしまいます。

 ******** Packed してないデータストラクト ********               
 B1 = 1                                                          
 B2 = 2                                                          
 B3 = 246210                                                     
 B3 HEX = 3c1c2                                                  
 C1 = S                                                          
 C2 = T                                                          
 STR = RING                                                      
 ******** Packed したデータストラクト ********                   
 B1 = 1                                                          
 B2 = 2                                                          
 B3 = 3                                                          
 C1 = A                                                          
 C2 = B                                                          
 STR = STRING

[つまりどうゆうこと?]

Cのデータストラクチャーは、_Packedを指定しないと、プログラムがアクセスしやすいバイトごとに、 サブフィールドを割り当てます。AS/400の場合4バイトの境界合わせがおこなわれます。

4バイト+2バイト+4バイト=10バイトの定義が実際は、

4バイト+2バイト+(使用されない2バイト)+4バイト=12バイトとなります。

これに伴なって以降のサブフィールドのデータがずれてしまいます。

上記の場合、データは

00 00 00 01 00 02 00 00 00 03 c1(A) c2(B) ..... と並んでいます。

データストラクチャーONEでは、

00 00 00 01 = B1
00 02 = B2
00 00 境界合わせのために使用されない2バイト
00 03 c1(A) c2(B) = B3(x03c1c2=246210) となっていまいます。

RPGには境界合わせというものがありませんし、コーディングするときに、初めの位置と終わりの位置を定義するので この様なことはありません。

一般的に、境界合わせした方が、処理自体は高速に処理できますので、RPGなどとデータストラクチャーのやり取りなど を行うのでなければ、_Packedを使用する必要はありません。