Supposons que j'ai la boucle pour la boucle qui stocke les zéros dans un tableau à l'aide de pointeurs comme celui-ci:
int *vp, values[5]; for(vp = &values[5-1]; vp >= &values[0]; vp--) *vp = 0;
3 Réponses :
En supposant qu'un pointeur équivaut à un entier non signé, nous pouvons voir que le problème n'existerait que si Pour visualiser le problème, passons à travers ce qui se passe, en supposant que Il s'agit également de comportement non défini en fonction de la norme (comme vous pouvez aborder un élément après un tableau, mais pas avant de cela), mais en réalité, cela ne devrait jamais échouer sur un système réaliste. P> p> valeurs code> a commencé à l'adresse 0, auquel cas le pointeur envelopperait après avoir été décrémenté et devenir uint_max code>. valeurs code> commence à l'adresse 0x0: p> vp code> ne serait jamais inférieur à la valeur minimale d'un pointeur (qui correspond à une boucle infinie (en supposant que toute la mémoire est écritable) ou une défaillance de la segmentation. p>
Donc, il est prudent d'utiliser ceci ou je peux vérifier plus que possible.
@ ashish2expert oui, c'est mon évaluation qu'il est sûr, à moins que vous traitiez avec un système très étrange (que vous n'êtes probablement pas ici).
Ce code peut échouer sur les implémentations avec des pointeurs de segment et décalage, mais cela peut également échouer car l'optimiseur est autorisé à supposer que vp> = & valeurs [0] code> n'est jamais exécuté avec vp < / code> ne pointant pas sur un élément du tableau ou un au-delà (parce que cela serait un comportement indéfini). Par conséquent, l'optimiseur peut se comporter comme si cette expression est toujours vraie et peut l'éliminer, entraînant une boucle infinie.
@ERICPOSTPISCHIL Dans ce cas, je pense que votre optimiseur doit être moins optimisante.
Ce code n'est pas en sécurité, même si des architectures anciennes ou exotiques du processeur sont exclues. P>
L'optimiseur d'un compilateur intègre de nombreuses règles sur la langue. Quand il voit Les règles et mécanismes intégrés dans l'optimiseur peuvent donc décider que vp> = et valeurs [0] code>, où valeurs code> est une matrice, l'optimiseur est autorisé à supposer que vp code> pointe sur un tableau élément ou un au-delà de la matrice, car sinon l'expression n'est pas définie par le langage C. P>
vp> = & valeurs [0] code> est toujours vrai, il peut donc produire du code comme si pour (vp = & valeurs [5 -1];; VP -) code> avait été écrit. Il en résulte une boucle sans condition de résiliation et un comportement supplémentaire non défini lorsque * vp = 0 code> est évalué avec vp code> pointant en dehors du tableau. P>
Oui, c'est possible, mais c'est probablement un peu improbable, à moins que vous n'ayez certains drapeaux d'optimisation définis. Si je me souviens bien, GCC a une option qui brise des boucles comme ça, mais elle est désactivée par défaut, et Clangs Optimizer ne touchera même pas de choses comme ça.
@ RICHARDJ.ROSSIII: Conservez-vous que ce code est en sécurité selon la norme C, ou simplement en sécurité si vous avez des connaissances spécifiques sur certains compilateurs? S'il vous plaît citer la documentation en supportant cela.
int *vp, values[5];
for(vp = &values[5-1]; vp ; vp = (vp > &values[0]) ? vp-1 : NULL; ) {
*vp = 0;
}
Il est «indéfini», mais sur 95% des systèmes, tout ira bien. Le scénario seul i> où la comparaison échouera sera si
et valeurs [0] code> == 0x0.Probablement plus de 95%. =)
Je parierai qu'il ne fonctionnerait pas sur la mise en œuvre de C sur des machines Symbolics Lisp. Je n'ai aucune idée de savoir s'il y a toujours une utilisation, cependant; La société a été étrangère il y a presque 20 ans.
Je le reprends, cela aurait pu travailler. Symbolique C vérifie les limites effectuées, mais je ne pense que lorsque des pointeurs de déséroférance. Comme cela ne contient pas de la déréférence, il a probablement fonctionné car
vp code> commence à pointer sur le même objet de tableau. Ses pointeurs ont été mis en œuvre comme une paire de tableau, index code>, et je ne pense pas qu'il y avait un problème avecindex code> décrémentation ci-dessous 0.Y a-t-il une raison spécifique que vous n'utilisez pas d'inégalité directe avec un post-décrément. Quelque chose comme
pour (vp = valse + n; vp--! = Valeurs;) code> oùn code> est la magnitude de votre tableau?@Whozcraig c'est une question de style
@ Richardj.rossiii Je demandais spécifiquement de répondre à l'observation de l'OP du texte mentionné sur l'évaluation d'un pointeur basé sur une matrice avant le premier élément, qui est en fait non défini, plutôt que sur un dernier élément, que est I> défini par la norme. Je n'ai pas voulu que ce soit un commentaire "C'est un autre moyen" et s'excuse s'il a été pris en tant que tel.