неверное использование гибкого массива - гибкий структурный массив как член другой структуры - PullRequest
10 голосов
/ 07 декабря 2010

Я начинаю узнавать об использовании структур в C. Это сложно и приятно. Излишне говорить, что я столкнулся с проблемой, которую я не могу понять. Я пытаюсь создать гибкий массив структур как член другой структуры, но получаю сообщение об ошибке:

неверное использование гибкого массива

Что я делаю не так?

#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;
}

РЕДАКТИРОВАТЬ 1

Это что-то вроде этого, я пытаюсь достичь

массив структур гибкой длины внутри другой структуры с использованием C

РЕДАКТИРОВАТЬ 2 *

О.К., таким образом, я, кажется, подхожу к созданию массива с переменным размером структуры неправильно. У меня есть 2 вещи, которые я пытаюсь. Первое, что я знаю, работает точно. Второе, что я хотел бы, если бы кто-нибудь смог проверить это для меня Я все еще изучаю указатели и хотел бы знать, является ли A тем же самым, что и B. B будет моим предпочтительным методом, но я не знаю, является ли он правильным. Я уверен в том, что когда я отлаживаю каналы, я вижу канал [0], канал [1], канал [2] и т. Д. Но я не очень уверен в отношении B, потому что когда я отлаживаю его, я вижу только адрес памяти и Перечисленные переменные структуры канала.

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;

** РЕДАКТИРОВАТЬ 3 ****

Да, они одинаковы. Не уверен, когда вы будете использовать один над другим, но

channel channels[NUM_CHANNELS]; 

равно:)

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 ]

17 голосов
/ 07 декабря 2010

Редактировать

Кажется, я сейчас помню, в чем проблема. Когда вы объявляете структуру с гибким массивом в качестве последнего члена, она делает что-то совершенно иное, чем вы думаете.

struct channelStruct channels[];

НЕ указатель, это массив на месте, который является смежным со структурой.

Способ, которым это предполагается использовать, заключается в том, чтобы наложить структуру на существующую память блока. Например, это полезно в сети, когда у вас есть пакет с данными переменной длины. Так что вы можете сделать что-то вроде:

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

Когда вы получаете пакет, вы переводите указатель на данные в указатель mydata, а затем поле varDataSize сообщает вам, сколько у вас есть. Как я уже сказал, следует помнить, что это все один непрерывный блок памяти, а data НЕ является указателем.

Старый ответ:

Я думаю, что это разрешено только в стандарте C99. Попробуйте скомпилировать с флагом -std=c99.

Также, смотрите эту ветку, Массив переменных в структуре

Также смотрите этот пост SO: Гибкие члены массива в C - плохо?

0 голосов
/ 07 декабря 2010

Я не эксперт в этой функции C, но мой здравый смысл говорит мне, что вы не можете определять объекты типа struct enginestruct, только указатели.Это относится к переменной engine в следующей строке:

struct enginestruct engine,*engineptr;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...