Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

t[i++]++

31 réponses
Avatar
candide
Bonjour


Juste une petite confirmation : si i est un entier et t est par exemple
un tableau d'entiers ou de flottants, une instruction du style

t[i++]++;


n'est pas indéterminée, n'est-ce pas ? Par exemple si i vaut
initialement 42, l'instruction ci-dessus incrémente d'une unité la
valeur de t[42] tout en passant à la case suivante du tableau t ie la
case 43. Je pose aussi la question car j'ai rarement lu ce genre
d'instruction dans du "vrai" code, peut-être n'est-ce pas considéré
comme très lisible, voire considéré comme source de trouble ou alors,
peut-être n'ai-je pas une fréquentation assez assidue du code "réel" ;)

Merci.

10 réponses

1 2 3 4
Avatar
Wykaaa
Samuel Devulder a écrit :
Marc Espie a écrit :

C'est qui "les gens" ? en C, ca n'a pas d'importance dans les cas ou ca



Les gens? Beaucoup de monde en réalité. 95% des gens que je croise
utilisent i++ par (mauvaise) habitude. J'ai rien contre si c'est une
habitude assumée comme tel, par contre il faut dire vite que ça n'a pas
d'importance... car c'est fondamentalement faux. Les expressions ++i et
i++ ne sont pas équivalentes.

donne le meme resultat, et c'est traditionnel d'ecrire i++.



Cela dépend du compilo et de ce qu'on appelle "avoir le même résultat".
Pour moi ca ne donne pas le résultat (dans le cas général):

int i = 3;
int j = i++; /* j vaut 3 */
int k = ++i; /* k vaut 5 */

par contre '++' avant ou après le i donne le même résultat sur la
variable i une fois l'instruction executée: elle a été incrémentée d'une
unité.

Je trouve que considérer que i++ est identique à ++i introduit une
légère confusion dans la tête du programmeur dont certains te
soutiennent après quelque temps de codage "par automatisme, sans
réfléchir" que le ++ peut être mis avant ou après sans que ça change
rien, ce qui est un mauvais réflexe.

il n'y a que en C++ qu'on prefere regulierement ++i pour des raisons
d'efficacite pour les classes definies par l'utilisateur.



Pas que C++, en C aussi.


Du coup pourquoi ne pas écrire ++t[i]; ++i; en espérant que le
compilo fusionne le t[i] et le ++i qui suit en l'instruction asm la
plus proche de la sémantique de t[i++].



Ca change quoi ? c'est aussi lisible dans les deux cas, de mon point de
vue.



Bah on peut aussi écrire à la pascal/ada et interdire l'usage des
opérateurs à effets de bords '++' et '--' (et les +=, -= et autre <<=
pendant qu'on y est :) ). Chacun fait ce qu'il veut.

Apres, si dans tes autres exemples, tu veux montrer que la difference
est subtile entre des constructions tres comprehensibles et des machins
illisibles... ben il suffit de le dire.

Quelqu'un qui sait programmer en C ne doit pas avoir le moindre souci
avec notre t[i++]++ du debut. Faut quand meme pas deconner, c'est les
regles de base du langage. S'il a des problemes avec, il peut
retourner faire du java ou du pascal...



En effet.. Mais perso je considère que quelqu'un qui écrit i++ en lieu
et place de ++i pas par habitude mais en étant persuadé que les deux
expressions sont équivalentes à i+=1 est quelqu'un qui ne connaît pas
assez le C (peut-être code t'il trop par automatisme). Seul ++i est
équivalent à i+=1, lui même équivalent à (i=i+1).

sam (<==Amiga still running :) )



Vous avez entièrement raison sur tous ces points. Les opérateurs ++, --
et dyadiques (+=, etc.) devraient être interdits d'usage, au moins dans
les logiciels où la fiabilité doit être supérieure au niveau nominal (au
sens de COCOMO). C'est d'ailleurs ce que j'ai pratiqué dans plusieurs
projets, en particulier militaires et pour le spatial.

J'ai été responsable du développement d'un compilateur C. Je connaissais
la norme ANSI (la première) quasiment par coeur. Je pensais et je
persiste à penser que des langages de la famille C (incluant C++ et
Java) sont des langages de programmation qui n'auraient jamais dû exister.
C'est une aberration du point de vue de la qualité logicielle et une
honte pour l'industrie informatique !
Il devrait y avoir un comité d'éthique pour l'informatique (un ordre des
informaticiens, comme l'ordre des médecins) pour interdire ce genre
d'horreur.
Avatar
Samuel Devulder
Marc Espie a écrit :
In article <4ad3738c$0$3737$,
Samuel Devulder wrote:
Cela dépend du compilo et de ce qu'on appelle "avoir le même résultat".
Pour moi ca ne donne pas le résultat (dans le cas général):

int i = 3;
int j = i++; /* j vaut 3 */
int k = ++i; /* k vaut 5 */




ce que j'appelle avoir le meme resultat, c'est avoir le meme comportement
observable.



Pourtant j et k n'ont pas la même valeur, preuve que ++i et i++ n'ont
pas le même comportement *observable*.

En fait tout dépend ce qu'on observe. La variable "i" toute seule ou
l'ensemble de l'espace d'état du programme, cad l'ensemble des
variables. En général on observe toutes les variables pour dire que la
sémantique est identique. Comparons le résultat de

int i = 3;
int j = i++;

et
int i = 3;
int j = ++i;

Effectivement dans les deux codes i est incrémenté de 1, mais j n'a pas
la même valeur à la sortie. On ne peut donc pas dire que ces deux codes
sont pas sémantiquement équivalents. (Désolé si c'est du coupage de
cheveux en 4.. mais j'aime pas lire que i++ et ++i sont équivalents).

Ce qui est le cas dans l'ecrasante majorite des utilisations
de i++ (a savoir: for (i = 0; i < n; i++) et assimies).



Oui, c'est le cas uniquement si on utilise pas la valeur retournée par
i++ (i.e. quand on l'utilise comme une instruction). Pour le coup je
préfère autant écrire ++i. Question de goût et de clarté du code et
d'aide pour le compilo comme tu l'indiquais. En fait ca sert à rien que
le compilo réserve un registre ou un bout de pile pour y stocker la
valeur initiale de i et tous ne sont pas capables de récupérer la valeur
allouée si elle n'est pas utilisée.

Maintenant si on veut faire propre (certains projets le requièrent, cf
les règles MISRA relatives aux effets de bords), on peut prendre la
convention d'interdire les opérateurs à effets de bords et écrire:
for(i = 0; i < n; i = i + 1)
Ca aussi son charme.. mais on s'éloigne du C façon "asm"-like proche de
l'architecture matérielle pour rentrer dans des langages de plus haut
niveau.


sam (<==Amiga still running :) )



Bah, les miens fonctionnent encore, mais je ne m'en sers plus. Me suis meme
jamais motive pour rajouter un disque et retrouver un systeme pour la tour
1200/060 qu'on m'avait file... ;(



Arf.. la passion s'épuise petit à petit.. normal.. en en plus, à chaque
fois que j'allume le miens il met de plus en plus de temps à démarer...
(disk dur qui plante et vérouille la chaine scsi. Mais bon c'est hors
topic :) )
Avatar
Patrick
Wykaaa a écrit :
Samuel Devulder a écrit :
Marc Espie a écrit :

C'est qui "les gens" ? en C, ca n'a pas d'importance dans les cas ou ca



Les gens? Beaucoup de monde en réalité. 95% des gens que je croise
utilisent i++ par (mauvaise) habitude. J'ai rien contre si c'est une
habitude assumée comme tel, par contre il faut dire vite que ça n'a
pas d'importance... car c'est fondamentalement faux. Les expressions
++i et i++ ne sont pas équivalentes.

donne le meme resultat, et c'est traditionnel d'ecrire i++.



Cela dépend du compilo et de ce qu'on appelle "avoir le même
résultat". Pour moi ca ne donne pas le résultat (dans le cas général):

int i = 3;
int j = i++; /* j vaut 3 */
int k = ++i; /* k vaut 5 */

par contre '++' avant ou après le i donne le même résultat sur la
variable i une fois l'instruction executée: elle a été incrémentée
d'une unité.

Je trouve que considérer que i++ est identique à ++i introduit une
légère confusion dans la tête du programmeur dont certains te
soutiennent après quelque temps de codage "par automatisme, sans
réfléchir" que le ++ peut être mis avant ou après sans que ça change
rien, ce qui est un mauvais réflexe.

il n'y a que en C++ qu'on prefere regulierement ++i pour des raisons
d'efficacite pour les classes definies par l'utilisateur.



Pas que C++, en C aussi.


Du coup pourquoi ne pas écrire ++t[i]; ++i; en espérant que le
compilo fusionne le t[i] et le ++i qui suit en l'instruction asm la
plus proche de la sémantique de t[i++].



Ca change quoi ? c'est aussi lisible dans les deux cas, de mon point de
vue.



Bah on peut aussi écrire à la pascal/ada et interdire l'usage des
opérateurs à effets de bords '++' et '--' (et les +=, -= et autre <<=
pendant qu'on y est :) ). Chacun fait ce qu'il veut.

Apres, si dans tes autres exemples, tu veux montrer que la difference
est subtile entre des constructions tres comprehensibles et des machins
illisibles... ben il suffit de le dire.

Quelqu'un qui sait programmer en C ne doit pas avoir le moindre souci
avec notre t[i++]++ du debut. Faut quand meme pas deconner, c'est les
regles de base du langage. S'il a des problemes avec, il peut
retourner faire du java ou du pascal...



En effet.. Mais perso je considère que quelqu'un qui écrit i++ en lieu
et place de ++i pas par habitude mais en étant persuadé que les deux
expressions sont équivalentes à i+=1 est quelqu'un qui ne connaît pas
assez le C (peut-être code t'il trop par automatisme). Seul ++i est
équivalent à i+=1, lui même équivalent à (i=i+1).

sam (<==Amiga still running :) )



Vous avez entièrement raison sur tous ces points. Les opérateurs ++, --
et dyadiques (+=, etc.) devraient être interdits d'usage, au moins dans
les logiciels où la fiabilité doit être supérieure au niveau nominal (au
sens de COCOMO). C'est d'ailleurs ce que j'ai pratiqué dans plusieurs
projets, en particulier militaires et pour le spatial.

J'ai été responsable du développement d'un compilateur C. Je connaissais
la norme ANSI (la première) quasiment par coeur. Je pensais et je
persiste à penser que des langages de la famille C (incluant C++ et
Java) sont des langages de programmation qui n'auraient jamais dû exister.
C'est une aberration du point de vue de la qualité logicielle et une
honte pour l'industrie informatique !
Il devrait y avoir un comité d'éthique pour l'informatique (un ordre des
informaticiens, comme l'ordre des médecins) pour interdire ce genre
d'horreur.


Bonsoir,
Quand on vous lit vos discutions, on a moins honte d'être débutant!
Merci
Avatar
Wykaaa
Patrick a écrit :

[couic]

Bonsoir,
Quand on vous lit vos discutions, on a moins honte d'être débutant!
Merci



Il n'y a jamais eu aucune honte à être débutant, surtout dans des
disciplines comme la programmation où la plupart des enseignements,
c'est un peu n'importe quoi.

J'ai réellement appris à bien programmer en entreprise, pas à l'école...
Avatar
Manuel Pégourié-Gonnard
Samuel Devulder scripsit:

Marc Espie a écrit :
In article <4ad3738c$0$3737$,
Samuel Devulder wrote:
Cela dépend du compilo et de ce qu'on appelle "avoir le même résultat".
Pour moi ca ne donne pas le résultat (dans le cas général):

int i = 3;
int j = i++; /* j vaut 3 */
int k = ++i; /* k vaut 5 */




ce que j'appelle avoir le meme resultat, c'est avoir le meme comportement
observable.



Pourtant j et k n'ont pas la même valeur, preuve que ++i et i++ n'ont
pas le même comportement *observable*.



Je crois qu'on est tous d'accord sur ce point. Personne ici ne prétend
(j'espère) que ++i et i++ ont le même sens dans l'absolu.

Le point est que dans certaines circonstances, ils sont
interchangeables. Marc défend l'idée que ces circonstances représentent
la vaste majorité des usages.

Oui, c'est le cas uniquement si on utilise pas la valeur retournée par
i++ (i.e. quand on l'utilise comme une instruction).



Voilà, ce qui compte c'est de savoir dans quels cas les deux sont
équivalents et dans quels cas ils en le sont pas. N'importe qui ayant
une connaissance de base du langage devrait être capable de faire cette
différence.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Avatar
espie
In article <4ad382bb$0$20053$,
Samuel Devulder wrote:
Marc Espie a écrit :
In article <4ad3738c$0$3737$,
Samuel Devulder wrote:
Cela dépend du compilo et de ce qu'on appelle "avoir le même résultat".
Pour moi ca ne donne pas le résultat (dans le cas général):

int i = 3;
int j = i++; /* j vaut 3 */
int k = ++i; /* k vaut 5 */




ce que j'appelle avoir le meme resultat, c'est avoir le meme comportement
observable.



Pourtant j et k n'ont pas la même valeur, preuve que ++i et i++ n'ont
pas le même comportement *observable*.

En fait tout dépend ce qu'on observe. La variable "i" toute seule ou
l'ensemble de l'espace d'état du programme, cad l'ensemble des
variables. En général on observe toutes les variables pour dire que la
sémantique est identique. Comparons le résultat de



Stop, je t'arrete tout de suite. J'ai choisi avec soin mon vocabulaire.
"comportement observable", c'est au sens de la norme. Il n'y a pas de
dependance sur ce qu'on observe. Le comportement observable est defini
sur l'ensemble du programme. Il y a evidemment des cas ou employer i++
ou ++i va changer le comportement observable, dans la classe des programmes
conformes. Il y a aussi des cas ou on va passer des programmes conformes aux
programmes a comportement indefini (je ne vois pas de cas ou une erreur
sur i++ conduirait a un comportement defini par l'implementation).

Mon point etait que, dans un grand nombre de cas, le choix de i++ ou ++i
n'a pas d'importance... dans les autres cas, *bien sur* qu'il a une
importance.

Dans les cas sans importance, le programmeur C choisira plus facilement i++
(c'est ce qui se fait d'habitude). Le programmeur C++ choisira plus
facilement ++i, parce que ca peut changer la vitesse de son code
(qui ne fait pas partie du comportement observable, mais qui presente
quand meme un interet pratique).

Apres, on peut arguer, comme le fait Wykaa, du bien fonde des constructions
de type i++ ou ++i. Perso, je suis plus pour l'eradication des
"programmeurs C" qui ne maitrisent pas ce genre de construction, au besoin
en les envoyant faire des conneries dans des langages dont je me fous, comme
java... ;-)
Avatar
Pierre Maurette
Marc Espie, le 13/10/2009 a écrit :

[...]

Mon point etait que, dans un grand nombre de cas, le choix de i++ ou ++i
n'a pas d'importance... dans les autres cas, *bien sur* qu'il a une
importance.



Le /grand nombre de cas/ c'est quand i++ ou ++i (remplacer i pas
/lvalue modifiable/ ce sera plus général) est une /void expression/.
Donc en particulier dans:

i++;

et

for(i = 0; i < MAXI; i++){/* bloc */}

Après, et je crois que c'est également votre opinion mais j'ai lu
d'autres choses dans ce fil, je pense qu'à ce niveau il faut se garder
de surenculer la mouche. En particulier écrire qu'il y a toujours une
différence entre for(i = 0; i < MAXI; i++) et for(i = 0; i < MAXI;
++i). Il y a la même différence entre ces deux expressions qu'entre
(void)++i et (void)i++, c'est à dire *des nèfles*. Et en pointant cette
différence qui n'existe pas, on sème la confusion sur la nature de la
boucle for(;;).

--
Pierre Maurette
Avatar
Samuel Devulder
Marc Espie a écrit :

Stop, je t'arrete tout de suite. J'ai choisi avec soin mon vocabulaire.
"comportement observable", c'est au sens de la norme.




Ah okok.. d'accord. Parce que j'avais lu dans ton propos ++i et i++ sont
équivalent sans se préoccuper de quoi que ce soit d'autres. Tu imagines
le débutant qui lit cela? brrrr.

Le programmeur C++ choisira plus
facilement ++i, parce que ca peut changer la vitesse de son code



Je ne vois pas pourquoi du point de vue C++ il y aurait une différence
d'exécution sur les types primitifs. Normalement le compilo C++ devrait
nous sortir la même panoplie d'optimisation et traduire i++ par la même
traduction asm que ++i quand "la valeur retournée importe peu" et
concerne un type primitif.

Apres, on peut arguer, comme le fait Wykaa, du bien fonde des constructions
de type i++ ou ++i.



Les normes de l'industrie automobile (MISRA par exemple) sont justement
là pour vérifier et controler ce genres d'usages (exemple: MISRA Rule
53). Par contre c'est plus subtil que du "tout ou rien" car dans
l'industrie on ne fait pas de religion, mais de la technique avec ses
propres contraintes (peu de ram/rom et/ou CPU lent).


Perso, je suis plus pour l'eradication des
"programmeurs C" qui ne maitrisent pas ce genre de construction, au besoin
en les envoyant faire des conneries dans des langages dont je me fous, comme
java... ;-)



Je me doutais bien que derrière le choix ++i et i++ tu voyais une espèce
de marque distinctive d'église de codeur. Bon moi je me fiche des
églises, je m'adapte au projet et ses contraintes techniques, c'est la
seule chose qui importe.
Avatar
espie
In article <4ad44f7f$0$296$,
Samuel Devulder wrote:
Marc Espie a écrit :

Stop, je t'arrete tout de suite. J'ai choisi avec soin mon vocabulaire.
"comportement observable", c'est au sens de la norme.




Ah okok.. d'accord. Parce que j'avais lu dans ton propos ++i et i++ sont
équivalent sans se préoccuper de quoi que ce soit d'autres. Tu imagines
le débutant qui lit cela? brrrr.

Le programmeur C++ choisira plus
facilement ++i, parce que ca peut changer la vitesse de son code



Je ne vois pas pourquoi du point de vue C++ il y aurait une différence
d'exécution sur les types primitifs. Normalement le compilo C++ devrait
nous sortir la même panoplie d'optimisation et traduire i++ par la même
traduction asm que ++i quand "la valeur retournée importe peu" et
concerne un type primitif.



Il n'y a pas de difference sur les types primitifs, mais l'existence des
templates et les habitudes de programmation generique fait que:
1/ on n'est pas forcement sur du fait qu'on a un type primitif.
2/ privilegier ++i par reflexe, ca fait un truc de moins a penser.

Je me doutais bien que derrière le choix ++i et i++ tu voyais une espèce
de marque distinctive d'église de codeur. Bon moi je me fiche des
églises, je m'adapte au projet et ses contraintes techniques, c'est la
seule chose qui importe.



Dans le monde ou je vis, ca marque effectivement le codeur C vs. le
codeur C++.

Pour les experimentes.

Pour les extra-terrestres autodidactes et debutants, il y a generalement
plein d'autres marques de fabrique qui permettent de detecter la bestiole
avant qu'elle fasse trop de degats... ;-)
Avatar
candide
Pierre Maurette a écrit :

Le /grand nombre de cas/ c'est quand i++ ou ++i (remplacer i pas /lvalue
modifiable/ ce sera plus général) est une /void expression/.




Abus de langage que de parler de "void expression" pour une expression
dont on ne "récupère" pas la valeur.
1 2 3 4