2008-12-09 9 views
2

Ce qui suit est une version simplifiée de ce que j'essaie de faire, car je suis sûr que vous ne voulez pas parcourir un ensemble complet de structs et de prototypes fonctionnels pour un Système de particules.ANSI C: Affectation de tableaux et de pointeurs aux tableaux

float const materials[24][4][4] = {{{...}}}; 
typedef struct EmitterStruct { float *material[4][4]; } Emitter; 
typedef struct ParticleStruct { float material[4][4]; } Particle; 
Emitter *myEmitter; 

Emitter * createEmitter(float *material[4][4]) 
{ 
    Emitter * newEmitter; 
    newEmitter = (Emitter *)malloc(sizeof(Emitter)); 
    newEmitter->material = materal; /* Returns "incompatable types in assignment" */ 
    return newEmitter;    /* I also tried newEmitter->material = &material */ 
} 

int main(char *argv, int argc) 
{ 
    myEmitter = createEmitter(materials[0]); 
} 

En substance, comme le montre le commentaire, j'obtiens une erreur de compilation. J'ai essayé ceci de plusieurs façons, même en utilisant "float material [4] [4]" dans la structure Emitter et la signature de createEmitter. Cependant, puis plus tard lorsque je tente de copier des valeurs dans une particule pour modificaitons en utilisant:

for (i=0; i++; i<4) 
{ 
    for (j=0; j++; j<4) 
    { 
     particle->material[i][j] = emitter->material[i][j]; 
    } 
} 

Je reçois une autre incompatibilité de type lors de la copie, même si tout est déclaré comme type float [4] [4]. Pour l'essentiel, je veux obtenir un tableau 4x4 sur un tableau de tableaux 4x4, en garder une trace dans la structure de l'émetteur, puis le copier dans la structure de la particule. Mais je veux seulement copier les valeurs une fois.

+1

J'ai changé le tag de ansi-c en c, puisque c'est le nom commun dans stackoverflow. J'espère que cela ne vous dérange pas. changez-le si vous ne l'aimez pas :) –

Répondre

1

En ce qui concerne le premier extrait, vous obtenez cette erreur car les tableaux en C ne sont pas assignables. Vous devez effectuer un memcpy pour copier des tableaux.

En ce qui concerne le deuxième extrait, vous avez un problème avec la ligne suivante:

particle->material[i][j] = emitter->material[i][j]; 

Le membre material dans Emitter est un tableau 2D de type float*. Le membre material dans Particle est de type float. Notez que l'un est un pointeur et l'autre non, ce qui explique pourquoi ils ne sont pas assignables.

Vous pouvez écrire ce qui suit:

particle->material[i][j] = *(emitter->material[i][j]); 

Mais cela en supposant que vous avez attribué ces pointeurs vers point de quelque chose. Alternativement, vous pouvez changer material en Emitter pour être un non-pointeur. Je ne peux pas vous dire ce que vous devez faire, car il m'est difficile de déchiffrer vos intentions exactes en fonction du code que vous avez donné.

+0

J'ai compris ce que je faisais mal. Et j'admets que c'est plutôt déroutant. Cependant, couper et coller le code complet aurait été 3 fichiers de valeur et encore plus confus. Merci quand même. –

0

Bien sûr, à la seconde où je demande de l'aide, je comprends exactement ce que je devais faire.

float const materials[24][4][4] = {{{...}}}; 
typedef struct EmitterStruct { float *material; } Emitter; /*Use just a plain pointer*/ 
typedef struct ParticleStruct { float material[4][4]; } Particle; 
Emitter *myEmitter; 

Emitter * createEmitter(float *material) /*Use a plain pointer here*/ 
{ 
    Emitter * newEmitter; 
    newEmitter = (Emitter *)malloc(sizeof(Emitter)); 
    newEmitter->material = material; 
    return newEmitter;    
} 

int main(char *argv, int argc) 
{ 
    myEmitter = createEmitter(materials[0]);/*This decays into a pointer*/ 
} 

Et pour la copie:

for (i=0; i++; i<4) 
{ 
    for (j=0; j++; j<4) 
    { 
     particle->material[i][j] = *(emitter->material[i * 4 + j]; 
    } 
} 

Doh ...

0

Je l'habitude d'être un expert en la matière. Malheureusement, je suis sorti de trop longtemps. Voici donc un extrait de code que j'ai écrit il y a environ 6 ans. Je pense que cela peut vous orienter dans la bonne direction.

// get a color histogram of an image 
int ***colorHistogram(PIXEL *inputImage, HEADER *imageHeader) 
{ 
    int x, y, z; 

    // a color histogram 
    int ***histo; 

    // allocate space for the histogram 
    histo = (int ***)malloc(256 * sizeof(int**)); 
    for(x=0; x<256; x++) 
    { 
     histo[x]=(int **)malloc(256 * sizeof(int*)); 
     for(y=0; y<256; y++) 
     { 
      histo[x][y]=(int *)malloc(256 * sizeof(int)); 

      // initialize the histogram 
      for(z=0; z<256; z++) 
       histo[x][y][z] = 0; 
     } 
    } 

    // fill the histogram 
    for (x = 0; x < imageHeader->width * imageHeader->height; x++) 
    { 
     histo[((int) inputImage[x].r)][((int) inputImage[x].g)][((int) inputImage[x].b)]++; 
    } 

return histo; 

}

Quoi qu'il en soit, je l'espère, cela aide.

3

Je réponds à votre question mise à jour (qui est apparue dans votre propre réponse). D'abord votre code:

float const materials[24][4][4] = {{{...}}}; 
typedef struct EmitterStruct { float *material; } Emitter; /*Use just a plain pointer*/ 
typedef struct ParticleStruct { float material[4][4]; } Particle; 
Emitter *myEmitter; 

Emitter * createEmitter(float *material) /*Use a plain pointer here*/ 
{ 
    Emitter * newEmitter; 
    newEmitter = (Emitter *)malloc(sizeof(Emitter)); 
    newEmitter->material = material; 
    return newEmitter;    
} 

int main(char *argv, int argc) 
{ 
    myEmitter = createEmitter(materials[0]);/*This decays into a pointer*/ 
} 

NO! Ce n'est pas la bonne façon.Il se désintègre en un pointeur - oui, mais pas un pointeur vers un flotteur! Si vous passez des matériaux [0], vous obtiendrez un float const[4][4] qui se désintègre en float const(*)[4] (un pointeur vers son premier élément), et ce pointeur est ce qui est passé. Ainsi, vous voulez changer dans ceci:

float const materials[24][4][4] = {{{...}}}; 
/*Use just a plain pointer to an array */ 
typedef struct EmitterStruct { float const (*material)[4]; } Emitter; 
typedef struct ParticleStruct { float material[4][4]; } Particle; 
Emitter *myEmitter; 

/*Use a plain pointer here. Bet keep it float const, not only float!*/ 
Emitter * createEmitter(float const (*material)[4]) 
{ 
    Emitter * newEmitter; 
    newEmitter = (Emitter *)malloc(sizeof(Emitter)); 
    newEmitter->material = material; 
    return newEmitter;    
} 

int main(int argc, char ** argv) /* you swapped args here */ 
{ 
    myEmitter = createEmitter(materials[0]); /* This decays into a pointer */ 
} 

Lire à ce sujet ici: what is `int *userMask[3][4]` pointing to?. Lisez ici comment passer correctement les tableaux: C++ strings: [] vs. *. Je vous recommande un bon compagnon de livre C ou C++ :)

+0

Accordé, je n'ai pas exécuté le code, mais êtes-vous sûr qu'il ne se transforme pas en un pointeur float lorsqu'il est transmis à la fonction createEmitter? C'est mauvais C, bien sûr, mais j'ai aussi le pressentiment que ça pourrait marcher. –

+0

il ne se transformera pas en float * par la vie de moi :) je veux dire qu'est-ce que vous attendez faire du matériel [1]? vous vous retrouverez à materials [0] [1] en sautant sizeof (float [4]) octets. si c'était un float *, en faisant du material [1], vous sauteriez seulement sizeof (float) bytes, finissant ainsi quelque part entre les dimensions. temps alien! –

+0

Oui, la taille du pointeur sera désactivée, mais je ne vois nulle part dans le code où cela est pertinent. Je pourrais me tromper si je n'ai pas regardé de près. –