Comportement indéfini ou pas ?

Le
David Côme
Bonjour à tous.
Est ce que ce code à un comportement indéfini ?

//iostream est inclue ,
int a; //(1)
cout<< a; // (2)

Pour ma part:
Je pense que la valeur de a est indéfinie car (1) créer une variable sur
la pile sans lui affecter de valeur.
Elle prend donc la valeur de ce qui se trouvait avant à cette place.
Il n'y a pas de moyen de connaitre cette valeur. La valeure de a est
indéfini même si certain compilo réalisé une affectation par défaut
(je pense à VC++ en mode débug , on peut confirmer ?)

Par contre la 2eme ligne, elle a un comportement totalement défini.Elle va
afficher la valeur de a, qui peut être n'importe quoi.

Suis-je dans le vrai ?

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
Fabien LE LEZ
Le #1136166
On Wed, 27 Feb 2008 18:56:42 +0100, David Côme
int a; //(1)


Jusque-là, pas de problème, même si l'utilité d'un tel code m'échappe.

cout<< a; // (2)


C'est de toutes façons un comportement indéfini : dans le meilleur des
cas, ça affichera un entier, sans qu'il soit possible d'en prévoir la
valeur à l'avance.

Il me semble que selon la norme, c'est un comportement indéfini tout
court (On ne peut pas du tout prévoir le comportement du code) ;
toutefois, en pratique, je m'attendrais à ce qu'un entier quelconque
soit effectivement affiché. Et il y a même de bonnes chances pour que
ce soit le même à chaque exécution, tant qu'on ne recompile pas.

Anthony Fleury
Le #1136165
Bonjour à tous.


Bonjour,

Est ce que ce code à un comportement indéfini ?

//iostream est inclue , ...
int a; //(1)
cout<< a; // (2)

Pour ma part:
Je pense que la valeur de a est indéfinie car (1) créer une variable sur
la pile sans lui affecter de valeur.
Elle prend donc la valeur de ce qui se trouvait avant à cette place.
Il n'y a pas de moyen de connaitre cette valeur. La valeure de a est
indéfini même si certain compilo réalisé une affectation par défaut
(je pense à VC++ en mode débug , on peut confirmer ?)

Par contre la 2eme ligne, elle a un comportement totalement défini.Elle
va afficher la valeur de a, qui peut être n'importe quoi.

Suis-je dans le vrai ?


Si on considère la plupart des implémentations connues, ça donnera en
effet un affichage d'une valeur aléatoire et en effet le comportement
peu changer en mode debug selon les compilateurs.

Cependant, au regard de la norme, ce code est indéfini car accède à une
variable non initialisée (en considérant (1) automatique).

Entre autre, a peut très bien contenir une valeur "invalide" pour le
système ("trap value") qui ferait remarquer au-dit système que la
variable utilisée ne l'est pas d'une manière conforme.

Anthony

David Côme
Le #1136731
On Wed, 27 Feb 2008 19:10:55 +0100, Fabien LE LEZ wrote:

On Wed, 27 Feb 2008 18:56:42 +0100, David Côme
int a; //(1)


Jusque-là, pas de problème, même si l'utilité d'un tel code m'échappe.



Ce code n'a pas d'utilité propre. C'est juste pour illustre l'utilisation
d'une variable non initialisée.

cout<< a; // (2)


C'est de toutes façons un comportement indéfini : dans le meilleur des
cas, ça affichera un entier, sans qu'il soit possible d'en prévoir la
valeur à l'avance.

Normal.


Il me semble que selon la norme, c'est un comportement indéfini tout
court (On ne peut pas du tout prévoir le comportement du code) ;
Je ne savais pas.


toutefois, en pratique, je m'attendrais à ce qu'un entier quelconque
soit effectivement affiché. Et il y a même de bonnes chances pour que
ce soit le même à chaque exécution, tant qu'on ne recompile pas.



Comme moi.


Jean-Marc Bourguet
Le #1138374
Fabien LE LEZ
On Wed, 27 Feb 2008 18:56:42 +0100, David Côme
int a; //(1)


Jusque-là, pas de problème, même si l'utilité d'un tel code m'échappe.

cout<< a; // (2)


C'est de toutes façons un comportement indéfini : dans le meilleur des
cas, ça affichera un entier, sans qu'il soit possible d'en prévoir la
valeur à l'avance.

Il me semble que selon la norme, c'est un comportement indéfini tout
court (On ne peut pas du tout prévoir le comportement du code) ;


J'ai pas vérifié, mais c'est ce que je pense. En particulier, ça peut être
une valeur déclanchant une exception (trois cas plausibles: la
représentation de ce qui serait -0 sur une machine en complément à 1 ou
grandeur et signe qui n'admet pas de -0; mauvais tags sur une machine où
les valeurs ont un tag; il y a eu une machine n'ayant que des nombres en
virgule flottante, mais où certaines opérations trappaient si une donnée
n'était pas entière).

toutefois, en pratique, je m'attendrais à ce qu'un entier quelconque soit
effectivement affiché.


Sur les machines courantes, c'est le comportement le plus vraissemblable.

Et il y a même de bonnes chances pour que ce soit le même à chaque
exécution, tant qu'on ne recompile pas.


Ca dépend de ce que tu appelles exécution. Ca ne m'étonnerait pas trop que
ceci

void f(int i) { int k = i; }
void g() { int a; std::cout << a << std::endl; }

int main() {
f(42);
g();
f(36);
g();
}

affiche 42 puis 36.

Et ca dépend aussi du système, tous ne remettent pas toute la mémoire à 0
entre processus (c'est certainement une mauvaise idée de ne pas le faire
sur des machines à usage général).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Sylvain
Le #1138899
Anthony Fleury wrote on 27/02/2008 19:29:

Est ce que ce code à un comportement indéfini ?

//iostream est inclue , ...
int a; //(1)
cout<< a; // (2)

Entre autre, a peut très bien contenir une valeur "invalide" pour le

système ("trap value") qui ferait remarquer au-dit système que la
variable utilisée ne l'est pas d'une manière conforme.


j'ai du mal à saisir la finesse de l'indéfinition.
je ne vois ici qu'une imprévision (non connaissance d'une valeur
aléatoire, ou comment se paraphraser).

surtout je ne vois pas ce que serait un *int* "invalide" !!
vous avez des machines sur lesquelles un int, disons 32 bits, peut
contenir toutes les valuers entières entre 0x00000000 et 0xFFFFFFFF
*plus* d'autres valeurs invalides ???

Sylvain.


Gabriel Dos Reis
Le #1139992
Sylvain
| Anthony Fleury wrote on 27/02/2008 19:29:
| >
| >> Est ce que ce code à un comportement indéfini ?
| >>
| >> //iostream est inclue , ...
| >> int a; //(1)
| >> cout<< a; // (2)
| >>
| > Entre autre, a peut très bien contenir une valeur "invalide" pour le
| > système ("trap value") qui ferait remarquer au-dit système qu e la
| > variable utilisée ne l'est pas d'une manière conforme.
|
| j'ai du mal à saisir la finesse de l'indéfinition.
| je ne vois ici qu'une imprévision (non connaissance d'une valeur
| aléatoire, ou comment se paraphraser).
|
| surtout je ne vois pas ce que serait un *int* "invalide" !!
| vous avez des machines sur lesquelles un int, disons 32 bits, peut
| contenir toutes les valuers entières entre 0x00000000 et 0xFFFFFFFF
| *plus* d'autres valeurs invalides ???

So ?

-- Gaby
Sylvain
Le #1139991
Gabriel Dos Reis wrote on 27/02/2008 23:37:
|
| surtout je ne vois pas ce que serait un *int* "invalide" !!
| vous avez des machines sur lesquelles un int, disons 32 bits, peut
| contenir toutes les valuers entières entre 0x00000000 et 0xFFFFFFFF
| *plus* d'autres valeurs invalides ???

So ?


so, vous avez des machines sur lesquelles un int, disons 32 bits,
peut contenir toutes les valuers entières entre 0x0 et 0xFFFFFFFF
*plus* d'autres valeurs, accessoirement invalides ???

la hiérarchie fr. utilise ISO-8859-1 pas UTF-8.

Sylvain.

Sylvain
Le #1142159
Gabriel Dos Reis wrote on 27/02/2008 23:37:
|
| surtout je ne vois pas ce que serait un *int* "invalide" !!
| vous avez des machines sur lesquelles un int, disons 32 bits, peut
| contenir toutes les valuers entières entre 0x00000000 et 0xFFFFFFFF
| *plus* d'autres valeurs invalides ???

So ?


so, vous avez des machines sur lesquelles un int, disons 32 bits,
peut contenir toutes les valuers entières entre 0x0 et 0xFFFFFFFF
*plus* d'autres valeurs, accessoirement invalides ???

la hiérarchie fr. utilise ISO-8859-1 pas UTF-8.

Sylvain.

Gabriel Dos Reis
Le #1147076
Sylvain
| Gabriel Dos Reis wrote on 27/02/2008 23:37:
| > | | surtout je ne vois pas ce que serait un *int* "invalide" !!
| > | vous avez des machines sur lesquelles un int, disons 32 bits, peut
| > | contenir toutes les valuers entières entre 0x00000000 et 0xFFFFF FFF
| > | *plus* d'autres valeurs invalides ???
| > So ?
|
| so, vous avez des machines sur lesquelles un int, disons 32 bits,
| peut contenir toutes les valuers entières entre 0x0 et 0xFFFFFFFF
| *plus* d'autres valeurs, accessoirement invalides ???

et donc ?

-- Gaby
Jean-Marc Bourguet
Le #1143254
Sylvain
surtout je ne vois pas ce que serait un *int* "invalide" !!


J'ai donné 3 cas de machines ayant existés où la non initialisation
pourrait fournir un int invalide. Je ne sais pas s'il y a eu des
implémentations de C++ pour ces machines, mais le C++ est conçu pour y
permettre une implémentation sans lui imposer d'initialiser toutes les
variables. On peut aussi parfaitement imaginer une implémentation qui
vérifierait dynamiquement la non utilisation de variables non intialisées.

Une autre source de problèmes, même avec des machines où toutes les
représentations sont valides, ce sont les optimisations. A partir du
moment où le comportement est formellement indéfini, le compilateur peut
supposer qu'il n'arrive pas et laisser ses algorithmes d'optimisation se
comporter n'importe comment si l'hypothèse n'est pas vraie. N'importe
comment, ca peut avoir des effets non causals, ou inconsitants.

int x; //0
for (i = 0; i < 10; ++i) {
if (f(i)) x = g(i);
}
std::cout << x << std::endl; //1
int y;
for (i = 0; i < 10; ++i) {
if (h(i)) { y = p(i); x = q(i); }
}
std::cout << x << " " << y << std::endl; //2

peut parfaitement afficher deux fois des valeurs différentes pour x même si
f(i) et h(i) ne retourne jamais true. Raisonnement pas hors de portée des
techniques d'optimisation actuelles:

x est non initialisé en 0, utilisé en 1 donc on assigne une valeur entre
les deux.

même raisonnement pour y entre 1 et 2. Mais si y est assigné entre 1 et 2,
x l'est aussi, donc x a deux utilisations distinctes (entre 0 et 1 et entre
1 et 2) et donc la valeur de x ne doit pas être conservée après 1, pour
diminuer la pression sur l'allocateur de registre, on introduit une
variable en plus pour ce deuxième intervalle.

L'allocateur fait son boulot et assigne des registres différents à x pour x
entre 0 et 1 et entre 1 et 2. Résultat, deux valeurs différentes pour x
sont affichées.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Publicité
Poster une réponse
Anonyme