Defining byte alignment

Correct byte alignment ensures that an API reads the data from the beginning of a record rather than at some other point. Here are the program examples that show the incorrect and correct ways of defining byte alignment.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

Incorrect program example: Defining byte alignment

This program illustrates byte alignment while defining a structure. This is shown at (1). Four-byte alignment is required when using this program.

Variable-length records must begin on a 4-byte boundary. As shown at (1), the variable-length record CCSID_rec is not beginning on a 4-byte boundary. When the API accesses the CCSID_rec record, 4-byte alignment is forced by padding the first 3 bytes of the CCSID_rec between the replace field and the start of the CCSID_rec record. (2) shows that the variable-length record is not 4-byte aligned (the value is 13, which is not divisible by 4). The correct coding is shown at (3).

Note: Not all APIs require a 4-byte boundary. APIs based on service programs, such as the Add Exit Program (QusAddExitProgram) API, require a 4-byte boundary.
/*****************************************************************  */
/*                                                                  */
/*Program Name: PGM1                                                */
/*                                                                  */
/*Program Language:  ILE C                                          */
/*                                                                  */
/*Description:    This program illustrates improper byte            */
/*                alignment when using variable length              */
/*                records.                                          */
/*                                                                  */
/*                                                                  */
/*Header Files Included:  <stdio.h>                                 */
/*                        <signal.h>                                */
/*                        <string.h>                                */
/*                        <stdlib.h>                                */
/*                        <qusrgfa1.h>                              */
/*                        <qusec.h>                                 */
/*                        <qliept.h>                                */
/*                                                                  */
/*  APIs Used:     QusAddExitProgram    - Add an exit program       */
/*                                                                  */
/********************************************************************/
/********************************************************************/
/*                     Includes                                     */
/********************************************************************/
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <qusrgfa1.h>
#include <qusec.h>
#include <qliept.h>
/********************************************************************/
/*                     Structures                                   */
/*                                                                  */
/********************************************************************/

typedef struct {                      /* Error code                 */
 Qus_EC_t ec_fields;
 char     exception_data[100];
} error_code_struct;

typedef struct {                      /* Exit program attribute keys*/
  int              num_rec;
  Qus_Vlen_Rec_4_t replace_rec;
  char             replace;
  Qus_Vlen_Rec_4_t CCSID_rec;                          (1)
  int              CCSID;
  Qus_Vlen_Rec_4_t desc_rec;
  char             desc[50];
} addep_attributes;
/********************************************************************/
/*                                                                  */
/*                             main                                 */
/*                                                                  */
/********************************************************************/
int main()
{
  error_code_struct error_code;
  addep_attributes attrib_keys;

  /******************************************************************/
  /* Initialize the error code parameter.                           */
  /******************************************************************/
  error_code.ec_fields.Bytes_Provided=sizeof(error_code_struct);

  /******************************************************************/
  /* Set the total number of exit program attributes that we are    */
  /* specifying on the call.  We will let the API take the default  */
  /* for the attributes that we are not specifying.                 */
  /******************************************************************/
  attrib_keys.num_rec=3;
  /******************************************************************/
  /* Set the values for the three attributes that we will be        */
  /* specifying:                                                    */
  /*       Replace exit program    = 1     (CHAR(1) field)          */
  /*       Exit program data CCSID = 37    (BIN(4) field)           */
  /*       Exit program description='THIS IS A TEST EXIT PROGRAM'   */
  /*                                       (CHAR(50) field)         */
  /*                                                                */
  /* The structure for the exit program attributes defined above is */
  /* as follows:                                                    */
  /*                                                                */
  /*      typedef struct {                                          */
  /*        int              num_rec;                               */
  /*        Qus_Vlen_Rec_4_t replace_rec;                           */
  /*        char             replace;                               */
  /*        Qus_Vlen_Rec_4_t CCSID_rec;                             */
  /*        int              CCSID;                                 */
  /*        Qus_Vlen_Rec_4_t desc_rec;                              */
  /*        char             desc[50];                              */
  /*      } addep_attributes;                                       */
  /*                                                                */
  /* and the Qus_Vlen_Rec_4_t structure is defined in               */
  /* qus.h (included by qusrgfa1) as:                               */
  /*                                                                */
  /*      typedef _Packed struct Qus_Vlen_Rec_4 {                   */
  /*        int  Length_Vlen_Record;                                */
  /*        int  Control_Key;                                       */
  /*        int  Length_Data;                                       */
  /*      **char Data[];-> this field is supplied by                */
  /*        the user                                                */
  /*      } Qus_Vlen_Rec_4_t;                                       */
  /*                                                                */
  /* This structure is mapped in bytes as follows:                  */
  /*      {                                                         */
  /*       BIN(4)   - num_rec                                       */
  /*       BIN(4)   - length variable length record for replace key */
  /*       BIN(4)   - replace key                                   */
  /*       BIN(4)   - length replace data                           */
  /*       CHAR(1)  - replace data                                  */
  /*       BIN(4)   - length variable length record for CCSID key   */
  /*       BIN(4)   - CCSID key                                     */
  /*       BIN(4)   - length CCSID data                             */
  /*       BIN(4)   - CCSID data                                    */
  /*       BIN(4)   - length variable length record for description */
  /*                  key                                           */
  /*       BIN(4)   - description key                               */
  /*       BIN(4)   - length description key                        */
  /*       CHAR(50) - description data                              */
  /*      }                                                         */
  /*                                                                */
  /******************************************************************/
  attrib_keys.replace_rec.Length_Vlen_Record=13;           (2)
  attrib_keys.replace_rec.Control_Key=4;
  attrib_keys.replace_rec.Length_Data=1;
  attrib_keys.replace='1';

  attrib_keys.CCSID_rec.Length_Vlen_Record=16;
  attrib_keys.CCSID_rec.Control_Key=3;
  attrib_keys.CCSID_rec.Length_Data=4;
  attrib_keys.CCSID=37;

  attrib_keys.desc_rec.Length_Vlen_Record=39;
  attrib_keys.desc_rec.Control_Key=2;
  attrib_keys.desc_rec.Length_Data=27;
  memcpy(&attrib_keys.desc,
         "THIS IS A TEST EXIT PROGRAM",27);

  /******************************************************************/
  /* Call the API to add the exit program.                          */
  /******************************************************************/
  QusAddExitProgram("EXAMPLE_EXIT_POINT  ",
                    "EXMP0100",
                    1,
                    "EXAMPLEPGMEXAMPLELIB",
                    "EXAMPLE EXIT PROGRAM DATA",
                    25,
                    &attrib_keys,
                    &error_code);

  if (error_code.ec_fields.Bytes_Available != 0)
  {
     printf("ATTEMPT TO ADD AN EXIT PROGRAM FAILED WITH EXCEPTION:%.7s",
             error_code.ec_fields.Exception_Id);
     exit(1);
  }


} /* end program */

Correct program example: Defining byte alignment

The following example program shows a CHAR(3) bytes reserved field being added to the structure to maintain 4-byte alignment as shown at (4). This corresponds to (1) in the incorrect coding example. The 3 reserved bytes are included in the length of the replace variable-length record. (3) shows the variable-length record is now 4-byte aligned (record length of 16 is divisible by 4). This corresponds to (2) in the incorrect coding example.

/********************************************************************/
/*                                                                  */
/*Program Name: PGM2                                                */
/*                                                                  */
/*Program Language:  ILE C                                          */
/*                                                                  */
/*Description:    This program illustrates proper byte              */
/*                alignment when using variable length              */
/*                records.                                          */
/*                                                                  */
/*                                                                  */
/*Header Files Included:  <stdio.h>                                 */
/*                        <signal.h>                                */
/*                        <string.h>                                */
/*                        <stdlib.h>                                */
/*                        <qusrgfa1.h>                              */
/*                        <qusec.h>                                 */
/*                        <qliept.h>                                */
/*                                                                  */
/*  APIs Used:     QusAddExitProgram    - Add an exit program       */
/*                                                                  */
/*                                                                  */
/********************************************************************/
/*                     Includes                                     */
/********************************************************************/
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <qusrgfa1.h>
#include <qusec.h>
#include <qliept.h>
/********************************************************************/
/*                     Structures                                   */
/********************************************************************/

typedef struct {                      /* Error code                 */
 Qus_EC_t ec_fields;
 char     exception_data[100];
} error_code_struct;

typedef struct {                      /* Exit program attribute keys*/
  int              num_rec;
  Qus_Vlen_Rec_4_t replace_rec;
  char             replace;
  char             Reserved[3];                        (4)
  Qus_Vlen_Rec_4_t CCSID_rec;
  int              CCSID;
  Qus_Vlen_Rec_4_t desc_rec;
  char             desc[100];
} addep_attributes;

/********************************************************************/
/*                                                                  */
/*                             main                                 */
/*                                                                  */
/********************************************************************/
int main()
{
  error_code_struct error_code;
  addep_attributes attrib_keys;

  /******************************************************************/
  /* Initialize the error code parameter.                           */
  /******************************************************************/
  error_code.ec_fields.Bytes_Provided=sizeof(error_code_struct);

  /******************************************************************/
  /* Set the total number of exit program attributes that we are    */
  /* specifying on the call.  We will let the API take the default  */
  /* for the attributes that we are not specifying.                 */
  /******************************************************************/
  attrib_keys.num_rec=3;

  /******************************************************************/
  /* Set the values for the three attributes that we will be        */
  /* specifying:                                                    */
  /*       Replace exit program    = 1     (CHAR(1) field)          */
  /*       Exit program data CCSID = 37    (BIN(4) field)           */
  /*       Exit program description='THIS IS A TEST EXIT PROGRAM'   */
  /*                                       (CHAR(50) field)         */
  /******************************************************************/
  attrib_keys.replace_rec.Length_Vlen_Record=16;             (3)
  attrib_keys.replace_rec.Control_Key=4;
  attrib_keys.replace_rec.Length_Data=1;
  attrib_keys.replace='1';

  attrib_keys.CCSID_rec.Length_Vlen_Record=16;
  attrib_keys.CCSID_rec.Control_Key=3;
  attrib_keys.CCSID_rec.Length_Data=4;
  attrib_keys.CCSID=37;

  attrib_keys.desc_rec.Length_Vlen_Record=39;
  attrib_keys.desc_rec.Control_Key=2;
  attrib_keys.desc_rec.Length_Data=27;
  memcpy(&attrib_keys.desc,"THIS IS A TEST EXIT PROGRAM",27);

  /******************************************************************/
  /* Call the API to add the exit program.                          */
  /******************************************************************/
  QusAddExitProgram("EXAMPLE_EXIT_POINT  ",
                    "EXMP0100",
                    1,
                    "EXAMPLEPGMEXAMPLELIB",
                    "EXAMPLE EXIT PROGRAM DATA",
                    25,
                    &attrib_keys,
                    &error_code);

  if (error_code.ec_fields.Bytes_Available != 0)
  {
     printf("ATTEMPT TO ADD AN EXIT PROGRAM FAILED WITH EXCEPTION: %.7s",
             error_code.ec_fields.Exception_Id);
     exit(1);
  }


} /* end program */