Struct with variable size of array

2019-07-27 06:56发布

问题:

I want to save data in arrays called plist. These arrays can vary in size and are part of a structure called ParticleList. I know how to create one list of size n[0]. n[0] for example is of size 2. Thus, a list of size 2. But what do I have to do, if I want to create several lists with size n[0], n[1], n[2] of type ParticleList?

To cut a long story short: How should I modify my code in order to access lists of variable size somehow like pl[numberOfList].plist[PositionInArray] = -1 or `pl[numberOfList] -> plist[PositionInArray] = -1'

#include <stdlib.h>
#include <stdio.h>

typedef struct{
    double *plist;
    int plistSize;
} ParticleList;

void sendPar(int *n, int nl){

    // Allocate memory for struct ParticleList
    ParticleList *pl = malloc(sizeof(ParticleList));

    // Allocate memory for list
    pl->plist = malloc(sizeof(double)*n[0]);

    // Fill list with data
    for(int k=0; k<n[0]; k++){
        pl->plist[k] = -1;
    }
    // Write size of list into file
    pl->plistSize = n[0];

    // Print data
    printf("Content of list:\n");
    for(int k=0; k<n[0]; k++){
        printf("%lf\n", pl->plist[k]);
    }
    printf("Size of list: %d\n", pl->plistSize);


    // Free memory
    free(pl);
}

int main(){
    // Number of lists
    int nl = 3;

    // Size of lists
    int n[nl];
    n[0] = 2;
    n[1] = 3;
    n[2] = 4;

    sendPar(n, nl);
}

回答1:

Do you mean something like this?

typedef struct{
    int plistSize;
    double* plist;
} ParticleList;

int main()
{
    int i, z = 0;

    /* Assuming you have three lists with three different sizes */
    double list1[2] = {-1.0, -1.1};
    double list2[3] = {-2.0, -2.1, -2.2};
    double list3[4] = {-3.0, -3.1, -3.2, -3.3};

    /* Create an array of three Particle Lists */
    ParticleList pl[3] = {{list1, 2},{list2, 3},{list3, 4}};

    /* Access the values in the Particle Lists */
    for(i = 0; i < 3; i++)
    {
        printf("ParticleList pl[%i]:\n", i);

        for(z = 0; z < pl[i].plistSize; z++)
        {
            printf("pl[%i].plist[%i] = %f\n", i, z, pl[i].plist[z]);
        } 
    }

    /* Change the first item of the second list */
    pl[1].plist[0] = 2.3;          
}

This way you can access each item in each list by

pl[<index of list>].plist[<index of list item>]

A bit more dynamic by using flexible array members (this way one of the lists can be replaced by another list of different size):

Note that I changed the struct!

typedef struct{
    int plistSize;
    double plist[];
} ParticleList;

int main()
{
    int i, z = 0;
    ParticleList *pl[3];

    /* Allocate memory for the lists */
    pl[0] = malloc( sizeof(ParticleList) + sizeof(double[2]) );
    pl[0]->plistSize = 2;
    pl[1] = malloc( sizeof(ParticleList) + sizeof(double[3]) );
    pl[1]->plistSize = 3;
    pl[2] = malloc( sizeof(ParticleList) + sizeof(double[4]) );
    pl[2]->plistSize = 4;

    /* Write the values in the Particle Lists */
    for(i = 0; i < 3; i++)
    {
        printf("ParticleList pl[%i]:\n", i);

        for(z = 0; z < pl[i]->plistSize; z++)
        {
            pl[i]->plist[z] = -i;
        } 
    }

    /* Print the values */
    for(i = 0; i < 3; i++)
    {
        printf("ParticleList pl[%i]:\n", i);

        for(z = 0; z < pl[i]->plistSize; z++)
        {
            printf("pl[%i]->plist[%i] = %f\n", i, z, pl[i]->plist[z]);
        } 
    }

    /* Change the first value of the second list */
    pl[1]->plist[0] = -1.1;

    /* Replace the first list by a new one */
    free(pl[0]);
    pl[0] = malloc( sizeof(ParticleList) + sizeof(double[5]) );
    pl[0]->plistSize = 5;  

    /* Assign some new values to the new list 1 */
    pl[0]->plist[0] = -4.1;
    pl[0]->plist[1] = -4.2;
    pl[0]->plist[2] = -4.3;
    pl[0]->plist[3] = -4.4;
    pl[0]->plist[4] = -4.5;

    /* Print the values */
    for(i = 0; i < 3; i++)
    {
        printf("ParticleList pl[%i]:\n", i);

        for(z = 0; z < pl[i]->plistSize; z++)
        {
            printf("pl[%i]->plist[%i] = %f\n", i, z, pl[i]->plist[z]);
        } 
    } 

    /* free all lists before exiting the program */
    for(i = 0; i < 3; i++)
    {
        free(pl[i]);
    }

    return 0;
}


回答2:

It would seem you are looking for the language feature called flexible array member. It works like this:

typedef struct{
    int plistSize;
    double plist[];
} ParticleList;

ParticleList *pl = malloc( sizeof(ParticleList) + sizeof(double[n]) );
pl->plistSize = n;
...
free(pl);

Where n is the size you want plist to have.



标签: c struct