cpointersstructdoublestructure

How to use double pointers (pointer to pointer) for an array of structures properly in standard C?


I have an array of structures as a function parameter and the size of the array is dynamic. My coworker said that I'll have to use a double pointer since the values contained in the array of struct will be overwritten.

The parameter that will become a double pointer is the following :

xPIDConfig_t **pxPIDConfig

Here is what the structure looks like for the xPIDConfig_t :

typedef struct
{
    ePIDType_t ePIDType;
    /* Common fields for the different types of PID */
    float fLowerSaturationLimit;
    float fUpperSaturationLimit;
    float fOldInput;
    float fIError;
    uint32_t ulDeltaTime;
    eBool_t bSaturationEnable;
    eBool_t bAntiWindupEnable;
    eBool_t bNegativeErrorEmptyIError;
    
    union
    {
        /* Parallel PID fields */
        struct
        {
            float fProportionalGain;
            float fIntegralGain;
            float fDerivativeGain;
        }xParallelPID;
        /* Non-interactive PID fields */
        struct
        {
            float fControllerGain;
            uint32_t ulIntegralTime;
            uint32_t ulDerivativeTime;
        }xNonInteractivePID;
    }xUniqueFields;
}xPIDConfig_t;

The size of the array of pxPIDConfig will vary.

But I am not sure how to malloc that double pointer or even how to use the function containing the double pointer.

I was just wondering if anyone had a good example of code of how to use a function with a double pointer array of variating size? and how to properly change the values contained in the array itself inside a function?

Right now this is how I change the values within the function :

pxPIDConfig->ePIDType = ePIDType;
pxPIDConfig->fOldInput = 0;
pxPIDConfig->fIError   = 0;
pxPIDConfig->ulDeltaTime       = ulDeltaTime;
pxPIDConfig->bSaturationEnable = bIsSaturationEnable;
pxPIDConfig->bAntiWindupEnable = bIsAntiWindupEnable;
pxPIDConfig->bNegativeErrorEmptyIError = bNegativeErrorEmptyIError; 

when the pointer is double do I have to use double '->'? This is very confusing for me.

Thank you all for the help

/***************** EDIT ************************************

My function is working right now, but I got told I need to use memory allocation since the size of my arrays varies according to the number of loops I want to implement.

Here are the parameters of my function :

eError_t eControlCascadeInit( uint8_t ucNumberOfLoops, ePIDType_t *pePIDType, xPIDConfig_t **pxPIDConfig, float *pfLowerLimit, float *pfUpperLimit, uint32_t *pulDeltaTime, \
                            eBool_t *pbIsSaturationEnable, eBool_t *pbIsAntiWindupEnable, eBool_t *pbNegativeErrorEmptyIError, \
                            float *pfPGain, float *pfIGain, float *pfDGain, float *pfCGain, uint32_t *pulITime, uint32_t *pulDTime )

They're all arrays of size ucNumberOfLoops. All of them are read-only arrays, except for the pxPIDConfig one that is write-only. The function initializes all the xPIDConfig_t present in the array with the parameters passed to the function through array.

array[ 0 ] contains the parameters for the first PID controller being initialized.

array[ 1 ] contains the parameters for the second PID controller being initialized and so on...

It's like that for all the parameters in the function.

Hope it makes my question more clear?


Solution

  • Here you have an example of how to use double-pointer, to change the pointer in the function:

    void allocate(xPIDConfig_t **array, size_t size)
    {
        *array = malloc(sizeof(**array) * size);
    
        /* some examples of how to access the struct members via double pointer */
    
        (*array) -> ulDeltaTime = 100;
        (**array).ulDeltaTime = 100;
        (*(array + 5)) -> ulDeltaTime = 100;
        array[5] -> ulDeltaTime = 100;
        (*array[5]).ulDeltaTime = 100;
    
    }
    
    int main(void)
    {
        xPIDConfig_t *array;
    
        allocate(&array, 100);
        printf("%s\n", array ? "success" : "failure");
        free(array);
    }