Define byte alignment

Correct byte alignment ensures that data used with an API is correct. Byte alignment is also essential when APIs are used to retrieve and then print or display data.

When byte alignment is off, it causes the API to read the data at some point other than at the beginning of a record.

Note: Read the Code license and disclaimer information for important legal information.

Example of incorrect coding: 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. ILE APIs, such as QusAddExitProgram, do.
/*****************************************************************  */
/*                                                                  */
/*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 */

Example: Defining byte alignment of correct coding

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 */
Related concepts
Receiver variables