2010-12-07 5 views
8

Je commence à apprendre sur l'utilisation de structures en C. C'est stimulant et agréable. Inutile de dire que j'ai rencontré un problème que je n'arrive pas à comprendre. Je suis en train de faire un tableau de struct souple en tant que membre d'une autre struct mais je reçois une erreur:utilisation invalide de tableau flexible-tableau flexible struct en tant que membre d'une autre structure

invalid use of flexible array

Qu'est-ce que je fais mal?

#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

C'est quelque chose comme cela, je suis en train de réaliser

flexible length struct array inside another struct using C

EDIT 2 *

OK Je semble donc se rapprocher de la création d'un tableau de taille variable de struct w manière rong. J'ai 2 choses que j'essaye. La première que je connais fonctionne à coup sûr. La seconde je voudrais juste si quelqu'un pouvait vérifier la santé pour moi. J'apprends toujours sur les pointeurs et j'aimerais savoir si A est la même chose que B. B serait ma méthode préférée mais je ne sais pas si c'est correct. Je suis confiant sur un parce que quand je débogue des canaux je vois le canal [0], le canal [1] le canal [2] etc. Mais je ne suis pas si confiant au sujet de B parce que quand je débogue je vois seulement une adresse à la mémoire et les variables de la structure de canal répertoriées.

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 ils sont les mêmes. Vous ne savez pas quand vous utilisez un sur l'autre tho

channel channels[NUM_CHANNELS]; 

est égal :)

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; 
+0

Quelle plateforme et quel compilateur utilisez-vous? –

+0

J'utilise ios4 et gcc 4.2. J'ai suivi beaucoup d'exemples, mais je ne peux pas arriver à le casser – dubbeat

Répondre

14

Modifier

Je pense que je me souviens maintenant quel est le problème. Lorsque vous déclarez une structure avec un tableau flexible comme c'est le dernier membre, elle fait quelque chose de complètement différent de ce que vous pensez.

struct channelStruct channels[]; 

est pas un pointeur, il est un tableau en place qui est contiguë à la struct.

La façon dont ceci est destiné à être utilisé est de placer la structure sur une mémoire de bloc existante. Par exemple, cela est utile en réseau lorsque vous avez un paquet avec des données de longueur variable. Donc, vous pourriez faire quelque chose comme:

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

Lorsque vous recevez un paquet que vous lancez un pointeur vers les données à un pointeur mydata puis le champ varDataSize vous indique combien vous avez.Comme je l'ai dit, la chose à retenir est que c'est un bloc de mémoire contigu et datan'est PAS un pointeur.

Old Réponse:

Je pense que ce ne permettent que dans la norme C99. Essayez de compiler avec le drapeau -std=c99.

Aussi, voir ce fil, Variable array in struct

Voir aussi ce SO message: Flexible array members in C - bad?

+0

mettant ce drapeau ne semblait pas me débarrasser de l'erreur. Je lis les liens. – dubbeat

+0

@dubbeat: Voir la modification à ma réponse. –

+0

hmmmmm. C'est très difficile d'avoir la tête. Pourriez-vous me diriger dans la bonne direction d'un exemple illustrant cet exemple de paquet? Aussi serait-il sûr de supposer que cette méthode flexible de tableau ne convient pas aux types de structure ou est-ce juste la manière dont j'essaye de le faire? – dubbeat

0

Je ne suis pas un expert dans cette fonction C mais mon bon sens me dit que vous ne pouvez pas définir des objets du type struct enginestruct , seulement des pointeurs. Cela concerne la variable engine dans la ligne suivante:

struct enginestruct engine,*engineptr; 
+1

bien sûr vous pouvez définir des objets du type struct -ce que c'est- – dubbeat

+0

si vous pouvez le définir, quelle taille at-il (le compilateur a besoin de le savoir pour le mettre dans une structure ou sur la pile)? Je devine que si elle peut être définie, la partie de tableau sera de taille 0, donc ce ne sera pas très utile. – Bwmat

+2

Désolé, mais vous avez complètement tort. –

Questions connexes