11

I'm beginning to learn about the use of structs in C. It's challenging and enjoyable. Needless to say I've encountered a problem I can't seem to figure out. I'm trying to make a flexible struct array as a member of another struct but I'm getting an error:

invalid use of flexible array

What am I doing wrong?

#define NUM_CHANNELS 4

struct channelStruct {
    float volume;
    uint mute;
};


struct enginestruct
{
    float bpm;
    int synctimeinbeats;
    int synctimeinsamples;
    int currentbeat;
    int oneBeatInSamples;
    int samplerate;
    struct channelStruct channels[];
};

struct enginestruct engine, *engineptr;
struct channelStruct  channel, *channelptr;        


-(void) setupengine


{
    engineptr = &engine;
    engineptr->oneBeatInSamples = 22050;
    engineptr->samplerate = 44100;

    struct channelStruct *ch = (struct channelStruct *) malloc ( 
        NUM_CHANNELS*sizeof(struct channelStruct) );
    //error occurs here
    engineptr->channels = ch;
}

EDIT 1

It's something like this I am trying to achieve

flexible length struct array inside another struct using C

EDIT 2*

O.K so I seem to be approaching the creation of a variable sized array of struct the wrong way. I have 2 things that I'm trying. The first I know works for sure. The second I would just like if somebody could sanity check it for me. I'm still learning about pointers and would like to know if A is the same as B. B would be my preferred method but I don't know if its correct. I'm confident about a because when I debug channels i see channel[0],channel[1]channel[2] etc. But I'm not so confident about B because when I debug it I only see an address to memory and the variables of channel struct listed.

A

// pretty sure this is o.k to do but I would prefer 
// not to have to set the size at compile time.

struct enginestruct
{
    float bpm;
    int synctimeinbeats;
    int synctimeinsamples;
    int currentbeat;
    int oneBeatInSamples;
    int samplerate;
    channel channels[NUM_CHANNELS]; //is this technically a pointer?
};

B

//I'm not sure if this is valid. Could somebody confirm for me if 
//it is allocating the same amount of space as in A.

struct enginestruct
{
    float bpm;
    int synctimeinbeats;
    int synctimeinsamples;
    int currentbeat;
    int oneBeatInSamples;
    int samplerate;
    channel *channels;
};

//This only works if channel in the engine struct is defined as a pointer.
channel * ar = malloc(sizeof(*ar) * NUM_CHANNELS);
engineptr->channels = ar;

**EDIT 3****

Yep they are the same. Not sure when you would use one over the other tho

channel channels[NUM_CHANNELS]; 

Is Equal To :)

struct enginestruct
{
    float bpm;
    int synctimeinbeats;
    int synctimeinsamples;
    int currentbeat;
    int oneBeatInSamples;
    int samplerate;
    channel *channels;
};

channel * ar = malloc(sizeof(*ar) * NUM_CHANNELS);
engineptr->channels = ar;
2
  • What platform & and compiler are you using? Commented Dec 7, 2010 at 17:33
  • I'm using ios4 and gcc 4.2. I've followed plenty of examples but I just can't manage to crack it Commented Dec 7, 2010 at 17:35

1 Answer 1

20

Edit

I think I remember now what the problem is. When you declare a struct with a flexible array as it's last member it's doing something completely different than what you think.

struct channelStruct channels[];

is NOT a pointer, it is an in place array which is contiguous with the struct.

The way this is intended to be used is to lay the struct over an existing block memory. For instance, this is useful in networking when you have a packet with variable length data. So you might do something like:

struct mydata {
    // various other data fields
    int varDataSize;
    char data[];
}

When you receive a packet you cast a pointer to the data to a mydata pointer and then the varDataSize field tells you how much you've got. Like I said, the thing to remember is that it's all one contiguous block of memory and data is NOT a pointer.

Old Answer:

I think that's only allow in the C99 standard. Try compiling with the -std=c99 flag.

Also, see this thread, Variable array in struct

Also see this SO post: Flexible array members in C - bad?

Sign up to request clarification or add additional context in comments.

5 Comments

setting that flag didnt seem to rid me of the error. I'm having a read through the links.
hmmmmm. thats very difficult to get my head around. Could you point me in the right direction of an example illustrating the said packet example?Also would it be safe to assume that this flexible array method is not suitable for struct types or is it just the way I'm trying to do it?
@dubbeat: It's no problem to have a variable array of structs inside another struct. Just remember that var array has to be the last member of the outer struct, and that only the outer most struct can have a variable array. Look at the format for a TCP packet, it's a perfect example: networksorcery.com/enp/protocol/tcp.htm If you still don't understand, let me know and maybe I can write up a more in depth example later tonight.
@dubbeat: Another suggestion, it seems like you don't really need to use a variable array, why don't you just use a pointer in enginestruct? That will immediately solve your problem.
@Robert. Could you take a look at my "edit 2 method B" and let me know if its valid?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.