Quelqu'un pourrait-il s'il vous plaît me dire si une telle construction est valide ou non (c'est-à-dire pas une UB) en C ++. J'ai des segfault à cause de cela et j'ai passé quelques jours à essayer de comprendre ce qui se passe là-bas.
Clang(3.8): clang++ -O3 -S test.cpp leal 7(%rdi), %ebx movl .L_ZZ4mainE5array+28(,%rax,4), %esi movl $_ZSt4cout, %edi callq _ZNSolsEi movl $.L.str, %esi movl $1, %edx movq %rax, %rdi callq _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l GCC(5/7) g++-7 -O3 -S test.cpp leal 7(%rdi), %ebx movl $_ZSt4cout, %edi subq $16, %rsp .cfi_def_cfa_offset 32 movq %fs:40, %rax movq %rax, 8(%rsp) xorl %eax, %eax movabsq $425201762403, %rax movq %rax, (%rsp) movslq %ebx, %rax movl (%rsp,%rax,4), %esi call _ZNSolsEi movl $.LC0, %esi movq %rax, %rdi call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl %ebx, %esi
4 Réponses :
C'est un comportement normal. Le nom du tableau est en fait un pointeur au premier élément de la matrice. Et le tableau [n] est identique à * (array + n) p>
En cas de A [i + = n] code> L'expression
i + = n code> sera toujours évaluée avant d'accéder à l'index. Mais l'exemple que vous avez fourni invoque UB lorsque votre exemple de tableau contient seulement deux éléments et que vous accédez donc à des limites de la matrice. P>
Fourni argc est inférieur à -7 ou supérieur à -6 (mais oui, c'est probablement le problème).
@ Petera.schneider argc code> ne devrait pas être négatif que si cela n'est modifié ailleurs à l'intérieur
principal code>.
Vous avez un point - il est défini par l'exécution et je ne saurais pas de côté comment le rendre négatif à principal code>. Peut-être en fournissant des arguments de ligne de commande int_max + 7, mais je crains que la longueur de la ligne de commande ait lieu quelque part avant de cela.
Par lui-même Cependant, dans votre exemple code> tableau code> n'a que 2 éléments, et Array [argc + = 7] code> est OK, le résultat de
argc + 7 code> sera utilisé comme index sur
tableau code> . p>
argc code> n'est jamais négatif, votre code entraînera donc toujours une UB en raison d'une limite hors limites. Accès au tableau. P>
Votre cas est clairement un comportement non défini, car vous dépasserez les limites de la matrice pour les raisons suivantes: P>
premier, expression second, Par conséquent, UB. P> array [argc + = 7] code> est égal à
* ((tableau) + (argc + = 7)) code> et les valeurs des opérandes être évalué avant
+ code> est évalué (cf. ici ); Opérateur
+ = code> est une affectation (et non un effet secondaire), et la valeur d'une affectation est le résultat de
argc code> (dans ce cas) après l'affectation (cf. ici ). Par conséquent, le
+ = 7 code> est efficace pour les sous-domestiques; p>
argc code> est défini en C ++ pour ne jamais négatif (cf. ici ); Donc,
argc + = 7 code> sera toujours
> = 7 code> (ou un débordement entier signé en scénariste très irréaliste, mais toujours ub alors). P>
Si vous posez une question à propos de C ++ et UB, ne marquez pas d'autres langues. C est une langue totalement différente avec d'autres règles sémantiques et d'autres points d'UB.
Quant à votre question, sauf si
argc code> est
-6 code> ou
-7 code> alors vous utiliserez un indice hors limites et qui est bien sûr Ub. L'expression utilisée pour l'index doit être entièrement évaluée en premier et en C ++ toutes les variantes d'affectation sont des expressions simples.
Ma question est si un [i + = n] augmentera toujours i d'abord.
@DMitry oui bien sûr; Les problèmes ne se produisent que si vous utilisez ArgC ailleurs dans la même expression, car l'ordre de l'évaluation des sous-expressions dans une expression (et donc la propagation des effets secondaires) n'est généralement pas défini.
@DMitry avez-vous peut-être pensé à la sémantique de
argc ++ code>? Cette expression aurait la valeur d'origine, pré- i> comme un indice en argv; La nouvelle valeur ne serait visible que dans la prochaine déclaration. Mais l'expression
argc + = 1 code> (ou
+ = 7 code>) a la valeur de
argc code> après i> l'incrément.