Question

est-il sûr la conversion suivante?

int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};

for(int i=0;i<10;i++)
  for(int j=0;j<10;j++)
    b[i][j]=a[i];

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here!
    printf("%d\n",*x);

Je ne pense pas que la conversion ci-dessus dans la boucle de for est sûr (je pense qu'il est dépendant de la plateforme). S'il vous plait corrigez moi si je me trompe. Je suis surpris parce que le code compile sans donner aucun avertissement même lorsque compilé en utilisant les options de -Wall -pedantic dans gcc.

Était-ce utile?

La solution

Ce tout a une chance d'être légale pour une et une seule raison: l'objet 2D tableau de int est réinterprété comme un tableau d'objets de char. Bien que dans le cas général conduit à la mémoire réinterprétation un comportement non défini, la spécification du langage permet explicitement « tableau de [signé / non signé] CHAR » réinterprétations pour les objets de tout type.

Cependant, un problème de sécurité formelle est toujours là. La langue ne garantit pas que tout motif de bits est une valeur valide de type char. Votre tentative de lecture de la mémoire réinterprétées par type char peut théoriquement provoquer un comportement si elle rencontre une représentation de piège pour char. Pour être en sécurité, vous devez utiliser le type de unsigned char, qui est le seul type qui n'a pas de représentation piège. Bien sûr, une plate-forme avec un char de piégeage peut être appelé en toute sécurité « exotique ».

Pendant ce temps, votre sizeof(a + 1) ne semble pas avoir de sens. a + 1 est une expression de type int *. Pourquoi vous voudriez utiliser la taille du pointeur pour augmenter la valeur de votre x dans ce cas n'est pas clair pour moi. Que faisiez-vous atteindre?

En ce qui concerne l'absence d'avertissements ... je ne serais pas attendre le compilateur d'émettre des avertissements ici. GCC avertit souvent de type calembour (aka réinterprétation de la mémoire), mais depuis réinterprétations de char sont explicitement autorisés (comme je l'ai dit ci-dessus), il n'y a pas d'avertissement ici. De plus, moulages explicites ont généralement tendance à supprimer des avertissements, car ils sont une façon de dire au compilateur que vous ne voulez vraiment faire quelque chose, peu importe la façon erronée et / ou dangereux, il pourrait être.

Autres conseils

un casting de tout type de pointeur vers un char * est autorisé explicitement par le langage C. donc la plupart cela est très bien.

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

La première partie est fine x = (char*)&b[0]; établit un pointeur char au début du tableau. Le test est aussi bien x <= (char *)&b[9][9] sera vrai tant que points de x à l'intérieur du tableau.

x += sizeof(a+1) est la partie hasardeux. Sur la plupart des 32 bits architectures CPU sizeof (int *) juste arrive être les mêmes que sizeof (int), de sorte que ce code sera probablement travail , mais seulement par accident.

Je suis sûr que ce qui était prévu était x += sizeof(a[0]) ou x += sizeof(b[0]), mais étant donné que le code a effectivement fait ce qui était prévu, personne ne remarqué le bug.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top