Hello welcome to Better C Coding, in this lesson we’ll talk about using enum types as loop indexes. Enum as loop indexes are useful to express of a better way the type we want to iterate and don’t merge conceptual types. It prevents annoying casts and quality assurance warnings, making your code more readable and maintainable.

Imagine that we have a system which contains a certain amount of power supplies.

In our system initialization process, we need to check states of all the power supplies, so because enum is better than macros to iterate with, we decided to create a power supply enum type.

 

/*Available power supplies.*/

typedef struct

{

    PS_LB = 0u,

    PS_HB,

    PS_TI,

    PS_DRL,

    PS_MAX

}HS_PowerSupply_Type;

 

/*Initialize the power supplies independently of their state.*/

void PowerSupply_Init(void)

{

    /*Expressing HS_PowerSupply_Type PS_LB to iterate.*/

    uint8 index = 0u;

    for(index = 0u; index < (uint8) PS_MAX; index ++)

    {

            PowerSupply_Restart((HS_PowerSupply_Type) index);

    }

    /*…*/

}

 

Some of us got accustomed to use integer in for loop indexes; but it is also possible to use enum types as indexes as they are essentially integers.

At first glance, this code seems neat but it has a QAC warning regarding MISRA 2012 Rule 10.5 which stands that the casting of uint8 to HS_PowerSupply_Type enum type is inappropriate in the PowerSupply_Restart function. This is because it is probable that you can set an integer value that is big enough that it cannot be expressed by the enum type.

We can try to solve this QAC warning by using HS_PowerSupply_Type enum type as loop index instead of the uint8.

 

/*Initialize the power supplies independently of their state.*/

void PowerSupply_Init(void)

{

    /*Initial HS_PowerSupply_Type value equal to 0.*/

    HS_PowerSupply_Type index = PS_LB;

    for(index = PS_LB; index < PS_MAX; index ++)

    {

            PowerSupply_Restart(index);

    }

    /*…*/

}

 

We erased the annoying casts but if we check QAC again, we will find another MISRA warning: MISRA 2012 Rule 10.1: The HS_PowerSupply_Type enum type is an inappropriate operand for the operation ++. This is because an enum might have gaps between constants referring to values not possible to express.

 

typedef enum

{

    VRM_NORM = 0u, /*There is no enum constant for 1u and 2u integer*/

    VRM_LOW = 3u,

    VROM_OVER,

    VRM_MAX

}VRM_State_Type;

 

/*10ms VRM main task.*/

void VRM_Task(void)

{

    /*Initial VRM_State_Type value equal to 0.*/

    VRM_State_Type index = VRM_NORM;

    for(index = VRM_NORM; index < VRM_MAX; index ++)

    {

        /*Ups No VRM definition to 1 and 2*/

            SetVRMState(index);

    }

    /*…*/

}

 

Hence, the best solution is to ensure that the enum is consecutive and that the initial enum constant is always the first one. The way to solve this is in the enum declaration a comment should be used to make other developers aware of these constraints. Furthermore, in the for loop, the respective justification should be placed regarding the enum consecutiveness and the first enum constant place keeping.

A final remark, if the index is used only as an array index then the uint8 approach is the ideal one:

 

/*Calculate the PWM derate for all the power supplies.*/

void PWMDerate_Calculation(void)

{

    /*Expressing HS_PowerSupply_Type PS_LB to iterate.*/

    uint8 index = 0u;

    for(index = 0u; index < PS_MAX; index ++)

    {

        /*Clean the last derate value before making calculations*/

        derateSignal[index] = 0u;

    }

    /*…*/

}

Leave a Reply

Your email address will not be published. Required fields are marked *