2 votes

Différence entre les initialisateurs de tableaux

Je crée un tableau dans C d'une taille connue qui ne change jamais. Quelle est la différence entre les deux initialisateurs suivants ?

1.

GLuint boxArray[36];
for (GLuint i=0; i<36; i++) 
{
    boxArray[i] = i;
}

2.

GLuint boxArray[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35};

Lorsque j'intervertis les deux méthodes ci-dessus, seule la première fonctionne dans mon code. L'inspection des tableaux eux-mêmes semble très similaire (la seule différence étant que la deuxième méthode a des valeurs nulles pour deux éléments AU-DELÀ de la fin du tableau).

J'utilise le code suivant pour inspecter le tableau juste après l'avoir créé...

for (int j=0; j<39; j++) {
    NSLog(@"boxArray[%d] = %d", j, boxArray[j]);
 }

Les deux résultats sont identiques, à la petite différence près. J'écris volontairement au-delà de la fin du tableau afin d'inspecter les différences à cet endroit.

Je place ensuite le tableau dans un objet NSData qui est une variable d'instance de l'objet dans lequel se trouve ce code.... comme suit...

_boxArrayData  = [NSData dataWithBytes:boxArray length:sizeof(boxArray)];

Je peux inspecter les données de l'autre côté lorsque je retire les données de l'objet NSData et elles semblent identiques. Cependant, lorsque j'utilise les données (il s'agit d'un simple tableau d'index pour OpenGLES2.0), j'obtiens des résultats différents.

1voto

Cyral Points 5424
GLuint boxArray[36];
for (GLuint i=0; i<36; i++) 
{
    boxArray[i] = i;
}

Votre affectation boxIndeciesArray no boxArray ou vice-versa puisque vous avez dit que le premier avait fonctionné.

EDIT : Je vois que vous avez édité votre question pour corriger cela, pouvez-vous développer davantage sur la façon dont vous obtenez vos valeurs et exactement pourquoi cela ne fonctionne pas ?

1voto

AndreyT Points 139512

Vous définissez et initialisez un tableau de taille 36 . Puis vous imprimez son contenu comme s'il avait une taille 39 . Ceci, bien sûr, sort des limites du tableau et "imprime" les éléments inexistants au-delà de la fin. Le comportement est indéfini. Ce que vous "voyez" au-delà des limites du tableau (des zéros ou autre chose) n'a pas d'importance.

1voto

Il est probable que le second initialisateur soit traité comme une "constante" par le compilateur. Ces valeurs sont donc écrites dans le bloc de constantes de l'exécutable et pointées directement par la variable tableau.

Les zéros suivants sont donc probablement une autre valeur constante quelque part dans votre code. Le compilateur alignera ces deux valeurs côte à côte dans l'exécutable tant que votre code n'a pas réellement changé. L'ajout de nouvelles constantes peut changer cela à l'avenir.

Si vous regardez au-delà du bloc mémoire de votre tableau, vous verrez probablement d'autres valeurs constantes (y compris des chaînes de caractères reconnaissables)... en supposant que votre code soit suffisamment substantiel pour cela.

Le premier initialisateur n'a évidemment pas ce comportement, car la mémoire est allouée sur la pile et remplie plus tard. Comme la pile peut être allouée à des endroits différents à chaque exécution de votre programme, les valeurs après le sommet de la pile peuvent être différentes à chaque fois.

En résumé, le second initialisateur rend votre exécutable plus volumineux, mais il s'initialise BEAUCOUP plus rapidement puisqu'il ne fait que pointer votre variable vers une constante. Le premier initialisateur rendra votre exécutable plus petit de la taille du tableau, mais allouera la mémoire dynamiquement lorsque vous atteindrez cette partie de votre code. De plus, l'utilisation de la boucle pour le remplir sera beaucoup plus lente que le second (comparativement). Il est évident qu'une boucle de 36 éléments est toujours très rapide, mais une simple affectation de pointeur représente beaucoup moins de cycles.

0voto

Segmented Points 785

Ils devraient être équivalents, la seule raison à laquelle je peux penser pour laquelle vous auriez des valeurs au-delà de la fin du tableau est que vous sortez des limites dans le code avec lequel vous inspectez les tableaux.

Inspectez le tableau à l'aide d'un code comme celui-ci :

for (int i = 0; i < 36; i++)
    printf("%d: %d\n", i, boxArray[i]);

Vous devriez constater qu'ils sont effectivement équivalents.

Editar Vous ne pouvez pas sortir des limites du terrain. comportement non défini - tout peut arriver.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X