Evaluation d'une expression constante

Le
candide
Bonjour,

La norme dit :

6.6 Constant expressions
()
A constant expression can be evaluated during translation rather than
runtime,


Soit le programme suivant :

/*--*/
#include <stdio.h>

#define A 2
#define B 5

int main(void)
{
int i;

for (i = 0; i < A * B; i++)
printf("toto");

return 0;
}
/*--*/

Ai-je une quelconque garantie que l'expression A*B ne sera pas réévaluée
à chaque tour de boucle pendant l'exécution ?

Merci
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 4
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Erwan David
Le #17794041
candide
Bonjour,

La norme dit :

6.6 Constant expressions
(...)
A constant expression can be evaluated during translation rather than
runtime,


Soit le programme suivant :

/*--------------------------------*/
#include
#define A 2
#define B 5

int main(void)
{
int i;

for (i = 0; i < A * B; i++)
printf("toton");

return 0;
}
/*--------------------------------*/

Ai-je une quelconque garantie que l'expression A*B ne sera pas réévaluée
à chaque tour de boucle pendant l'exécution ?



Non. Cependant en pratique A*B sera évalué à la compilation.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Charlie Gordon
Le #17802431
"Erwan David"
candide
Bonjour,

La norme dit :

6.6 Constant expressions
(...)
A constant expression can be evaluated during translation rather than
runtime,


Soit le programme suivant :

/*--------------------------------*/
#include
#define A 2
#define B 5

int main(void)
{
int i;

for (i = 0; i < A * B; i++)
printf("toton");

return 0;
}
/*--------------------------------*/

Ai-je une quelconque garantie que l'expression A*B ne sera pas réévaluée
à chaque tour de boucle pendant l'exécution ?



Non. Cependant en pratique A*B sera évalué à la compilation.



Je dirais même plus : on peut être quasi-sûr que ce sera le cas, pour 2
raisons:
- le compilateur est obligé de savoir faire l'évaluation des expressions
constantes au moment de la compilation, sinon impossible de déclarer ``char
a[A * B]''.
- si d'aventure ce n'était pas le cas, le résultat serait quand même 10, le
donc programme fonctionnerait correctement, et le manque de performance dû à
cette lacune du compilo serait le cadet de tes soucis, le code généré pour
le reste du programme étant vraisemblablement tout aussi inefficace.

Si tu as des doutes, tu peux toujours écrire

for (i = 0; i < sizeof(char[A * B]); i++) ...

Mais c'est un style particulièrement laid.

--
Chqrlie.
Wykaaa
Le #17802791
candide a écrit :
Bonjour,

La norme dit :

6.6 Constant expressions
(...)
A constant expression can be evaluated during translation rather than
runtime,


Soit le programme suivant :

/*--------------------------------*/
#include
#define A 2
#define B 5

int main(void)
{
int i;

for (i = 0; i < A * B; i++)
printf("toton");

return 0;
}
/*--------------------------------*/

Ai-je une quelconque garantie que l'expression A*B ne sera pas réévaluée
à chaque tour de boucle pendant l'exécution ?

Merci


Un compilateur qui génèrerait du code pour réévaluer A*B a chaque tour
de boucle, il vaut mieux l'abandonner tout de suite parce que c'est
trivial à faire comme optimisation.
Antoine Leca
Le #17806651
En news:49172a5f$0$17384$, candide va escriure:
#include #define A 2
#define B 5
int main(void) {
int i;
for (i = 0; i < A * B; i++) printf("toton");
return 0; }

Ai-je une quelconque garantie que l'expression A*B ne sera pas
réévaluée à chaque tour de boucle pendant l'exécution ?



Garantie formelle, non. D'ailleurs, tu n'as pas non plus de garantie que le
compilateur ou le processeur ne fasse pas 5 additions du nombre 2 à chaque
tour de boucle (tu as seulement la garantie qu'il ne va /pas/ passer par une
adition des logarithmes de 2 et de 5); tu n'as même pas de garantie qu'il y
ait effectivement une boucle.

J'ai déjà vu des compilateurs (pas C, mais c'est un détail) qui remplaçait à
la compilation le programme ci-dessus par

int main(void) {
puts("totontotontotontotontotontotontotontotontotontoto");
return 0; }

Plus de i, plus de printf et un seul appel... Alors l'évaluation du produit
A*B, à ce niveau, c'est un détail de l'histoire...


En C, je ne pense pas que l'on rencontre de compilateur qui va sucrer
printf(), même si la norme le permet, parce qu'il est entré dans les mours
de pouvoir remplacer à l'édition des liens les fonctions de bibliothèque en
général, et malloc/free ou printf en particulier. Par contre, les
compilateurs optimisateurs vont dérouler la boucle, et réécrire le programme
ci-dessus sous la forme
int printf(const char*, ...);
int main(void) {
printf("toton"); printf("toton"); printf("toton"); printf("toton");
printf("toton"); printf("toton"); printf("toton");
printf("toton"); printf("toton"); printf("toton");
return 0; }
Et à partir de là, comme les compilateurs d'aujourd'hui ont des capacités
d'analyser les chaînes de format, il doit être possible de trouver un
compilateur qui vont fusionner les 10 chaînes de format entre elles, et
arriver à
int printf(const char*, ...);
int main(void) {
printf("totontotontotontotontotontotontotontotontotontoton");
return 0; }


Antoine
Jean-Marc Bourguet
Le #17807401
"Antoine Leca"
En news:49172a5f$0$17384$, candide va escriure:
#include #define A 2
#define B 5
int main(void) {
int i;
for (i = 0; i < A * B; i++) printf("toton");
return 0; }

Ai-je une quelconque garantie que l'expression A*B ne sera pas
réévaluée à chaque tour de boucle pendant l'exécution ?



Garantie formelle, non. D'ailleurs, tu n'as pas non plus de garantie que le
compilateur ou le processeur ne fasse pas 5 additions du nombre 2 à chaque
tour de boucle (tu as seulement la garantie qu'il ne va /pas/ passer par une
adition des logarithmes de 2 et de 5); tu n'as même pas de garantie qu'il y
ait effectivement une boucle.

J'ai déjà vu des compilateurs (pas C, mais c'est un détail) qui remplaçait à
la compilation le programme ci-dessus par

int main(void) {
puts("totontotontotontotontotontotontotontotontotontoto");
return 0; }

Plus de i, plus de printf et un seul appel... Alors l'évaluation du produit
A*B, à ce niveau, c'est un détail de l'histoire...



gcc arrive à

int main() {
puts("toto"); puts("toto"); puts("toto"); puts("toto"); puts("toto");
puts("toto"); puts("toto"); puts("toto"); puts("toto"); puts("toto");
return 0;
}

(Mais si je l'ai déjà vu supprimer du code mort ou remplacer des appels à
des fonctions standard par d'autres comme ici, je ne l'ai pas encore vu
fusionner des appels).

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Vincent Lefevre
Le #17832381
Dans l'article Charlie Gordon
- le compilateur est obligé de savoir faire l'évaluation des expressions
constantes au moment de la compilation, sinon impossible de déclarer ``char
a[A * B]''.



Euh... A * B pourrait très bien être effectué au lancement du
programme (même si ce n'est pas le cas en pratique).

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
Antoine Leca
Le #17833551
En news:20081113150454$, Vincent Lefevre va
escriure:
Dans l'article Charlie Gordon
- le compilateur est obligé de savoir faire l'évaluation des
expressions constantes au moment de la compilation, sinon impossible
de déclarer ``char a[A * B]''.



Euh... A * B pourrait très bien être effectué au lancement du
programme



Non. Si A*B donne une résultat négatif ou nul, le compilateur doit émettre
un diagnostic, ce qui impose de faire l'évaluation.


Antoine
Vincent Lefevre
Le #17836511
Dans l'article Antoine Leca
En news:20081113150454$, Vincent Lefevre va
escriure:
> Dans l'article > Charlie Gordon >
>> - le compilateur est obligé de savoir faire l'évaluation des
>> expressions constantes au moment de la compilation, sinon impossible
>> de déclarer ``char a[A * B]''.
>
> Euh... A * B pourrait très bien être effectué au lancement du
> programme



Non. Si A*B donne une résultat négatif ou nul, le compilateur doit émettre
un diagnostic, ce qui impose de faire l'évaluation.



On peut très bien détecter le signe du résultat sans effectuer le
produit!

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
Mickaël Wolff
Le #17836741
Vincent Lefevre a écrit :

On peut très bien détecter le signe du résultat sans effectuer le
produit!



En mathématique peut-être, mais en informatique pas forcément.
Surtout pas avec les nombres signés. Sans le calculer, c'est difficile
de savoir si (1 << 16) * 2 est positif ou négatif.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Vincent Lefevre
Le #17838871
Dans l'article Mickaël Wolff
Vincent Lefevre a écrit :



> On peut très bien détecter le signe du résultat sans effectuer le
> produit!



En mathématique peut-être, mais en informatique pas forcément.
Surtout pas avec les nombres signés. Sans le calculer, c'est difficile
de savoir si (1 << 16) * 2 est positif ou négatif.



1 est un entier signé positif, donc 1 << 16 est aussi positif, et
de même que (1 << 16) * 2. Rappel: il n'y a pas de wrapping sur
les entiers signés.

Mais bon, il suffit que le signe soit détectable dans certains
cas pour que dans ces cas-là, le compilateur ne soit pas obligé
d'effectuer le calcul à la compilation. Le compilateur peut aussi
émettre un diagnostic s'il estime que certains calculs sont trop
compliqués.

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
Publicité
Poster une réponse
Anonyme