Belgin Fish
Belgin Fish

Reputation: 19857

Initializing Array of Structure in C

I have the following structure

typedef struct {
    int buf[BUF_SIZE]; // the buffer
    size_t len; // number of items in the buffer
    pthread_mutex_t mutex; // needed to add/remove data from the buffer
    pthread_cond_t can_produce; // signaled when items are removed
    pthread_cond_t can_consume; // signaled when items are added
};

Initially I was simply initializing it as follows

buffer_t buffer = {
    .len = 0,
    .mutex = PTHREAD_MUTEX_INITIALIZER,
    .can_produce = PTHREAD_COND_INITIALIZER,
    .can_consume = PTHREAD_COND_INITIALIZER
};

Although I would like to initialize an array of buffer_t with those values, although I'm not quite sure how to properly do it.

Something like

buffer_t buffer[NUM_ARRAY] = {
    .len = 0,
    .mutex = PTHREAD_MUTEX_INITIALIZER,
    .can_produce = PTHREAD_COND_INITIALIZER,
    .can_consume = PTHREAD_COND_INITIALIZER
};

(Which I realize is incorrect)

Edit: I ended up using

buffer_t buffers[NUM_THREADS];

for (i = 0, i < 3, i ++) {
       buffers[i] = (buffer_t) {
                .len = 0,
                .mutex = PTHREAD_MUTEX_INITIALIZER,
                .can_produce = PTHREAD_COND_INITIALIZER,
                .can_consume = PTHREAD_COND_INITIALIZER
            };  
}

Upvotes: 0

Views: 318

Answers (4)

dbush
dbush

Reputation: 225344

If NUM_ARRAY isn't too big, you can do something like this:

#define NUM_ARRAY 3

buffer_t buffer[NUM_ARRAY] = {
    { {0}, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER},
    { {0}, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER},
    { {0}, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER}
};

Or you could explicitly code it like this:

buffer_t buffer[NUM_ARRAY];
int i;
for (i=0; i<NUM_ARRAY; i++) {
    memset(buffer[i].buf, 0, sizeof(buffer[i].buf));
    buffer[i].len = 0;
    buffer[i].mutex = PTHREAD_MUTEX_INITIALIZER;
    buffer[i].can_produce = PTHREAD_COND_INITIALIZER;
    buffer[i].can_consume = PTHREAD_COND_INITIALIZER;
}

EDIT:

So it looks like the PTHREAD_MUTEX_INITIALIZER and PTHREAD_COND_INITIALIZER macros can't be used in an assignment like this as it's meant to be used only in initializations and contains { and } characters.

So you need to use initialization syntax as others have suggested:

buffer_t buffer[NUM_ARRAY];
int i;
for (i=0; i<NUM_ARRAY; i++) {
    buffer[i] = (buffer_t) {
        0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER
    };
}

Upvotes: 3

cadaniluk
cadaniluk

Reputation: 15229

You need to specify the curly braces to initialize the array, so your last example is incorrect indeed.

There are multiple ways to initialize the whole array with the same struct every time:

  1. Initialize each array member explicitly. Example:

    buffer_t buffer[NUM_ARRAY] = {
        {
            .len = 0,
            .mutex = PTHREAD_MUTEX_INITIALIZER,
            ...
        },
        {
            .len = 0,
            .mutex = PTHREAD_MUTEX_INITIALIZER,
        },
        ...
    };
    

    This is pretty tedious, though. A standardese way would be to...

  2. Use a for loop:

    buffer_t buffer[NUM_ARRAY];
    for (size_t i = 0; i < NUM_ARRAY; ++i) {
        buffer[i] = (buffer_t) {
            .len = 0,
            .mutex = PTHREAD_MUTEX_INITIALIZER,
            ...
        };
    }
    

    Way better1. However, there's still...

  3. Designated initializer lists. Some of them have been standardized like ones you are using but this one hasn't. Therefore it's a non-standard GCC extension but worth to mention anyway. Example:

    buffer_t buffer[NUM_ARRAY] = {
        [0 ... (NUM_ARRAY - 1)] = {
            .len = 0,
            .mutex = PTHREAD_MUTEX_INITIALIZER,
            ...
        }
    };
    

I recommend the 2nd option, though.


1 The (buffer_t) { } syntax is available only since C99. If your compiler doesn't support it, use simple assignment per struct member.

Upvotes: 2

Samidamaru
Samidamaru

Reputation: 1081

Generally you can initialise an array of structs something like this:

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

typedef struct buffer_t {
    int a;
    int b;
    int c;
} buffer_t;

int main()
{
    int i;
    int NUM_ARRAY=4;

    buffer_t buffer[NUM_ARRAY];

    for(i=0; i<NUM_ARRAY; i++)
    {
        buffer[i].a = 0;
        buffer[i].b = 1;
        buffer[i].c = 2;
    };

    return 0;
}

I feel like you're after more than this though?

Upvotes: 0

Ctx
Ctx

Reputation: 18420

If your buffer is global, you can leave the initialization in this special case, because PTHREAD_MUTEX_INITIALIZER is a structure with all zeroes. Otherwise, you would have no other choice than to initialize all members or loop over it programmatically.

Upvotes: 0

Related Questions