C400

144. 構造体の受け渡しで悩んだら?

typedef構造体を関数の結果の変数として上位のプログラムに
EXPORTしている場合、変数が正しく渡されないというトラブルに
見舞われることがある。
何度見直してもどこにも間違いがないはずなのに
受取った変数の値にスレが生じる場合がある。
特に問題になるのはC言語のサービス・プログラム(*SRVPGM)から
上位がRPGやCOBOLである場合である。
_

[例]

0073.00 typedef struct {      
0074.00    char fldnam[10];   
0075.00    char flddmy[1];    
0076.00    char fldtyp[1];    
0077.00    char fldusg[1];    
0078.00    int  fldott;       
0079.00    int  fldinp;       
0080.00    int  fldbyt;       
0081.00    int  fldkta;       
0082.00    int  flddec;       
0083.00    char fldtxt[50];   
0084.00    char fldhns[2];    
0085.00    int  fldhnl;       
0086.00    char fldhng[64];   
0087.00    char fldch1[20];   
0088.00    char fldch2[20];   
0089.00    char fldch3[20];   
0090.00 } FLDBUF;             
0091.00 FLDBUF fldbuf;        

[解説]

このような構造体を結果の変数として上位のプログラムに渡すと
各要素のあいだに不明なスペースが不定期に挿入されていたりする。
この原因はC言語のコンパイラーが勝手に変数のあいだに
スペースを挿入してしまうからである。
このことはIBM マニュアルにも書かれていない。
ではどうすれば解決するだろうか?

[解決方法]

typedef structではなく typedef _Packed struct に変更する。

typedef _Packed struct { /* フィールド構造体 */
  char field[11];        /* フィールド名 */    
  char fldType;          /* タイプ */          
  long fldLen;           /* フィールド長 */    
  int  fldDec;           /* 小数桁 */          
  char fldUse;           /* 使用方法 */        
  char value[512];       /* 値 */              
  char fldIO;            /* O= 出力 B= 入力 */ 
  int  fldByte;          /* バイト数 */        
  int  fldPos;           /* 開始位置 */        
  char file[11];         /* ファイル */        
  int  valchk;           /* 妥当性検査の数 */  
  char values[31];       /* VALUES */          
  int  vallen;           /* VALUES 変換長 */   
  char colhdg[21];       /* 欄見出し */        
  char fldtxt[51];       /* テキスト */        
  char edtcde;           /* 編集コード */      
  char edtwrd[32];       /* 編集語 */          
  char mask[256];        /* 編集マスク */      
  int  msklen;           /* マスク長 */        
  int  rcvlen;           /* API 受取り長 */              
  char zerobal;          /* Zero balance fill character *
} FLDBUF;                                                
FLDBUF m_fldbuf;                                         

[解説]

typedef _Packed structを使うとコンパイラーが変数のあいだに
スペースを挿入するようなことはしない。
_

このテクニックはC言語に相当精通している人しか知らないテクニックであるので
ぜひ覚えておいて頂きたい。