char, signed char et unsigned char et les références

char, signed char et unsigned char et les références - C++ - Programmation

Marsh Posté le 16-11-2005 à 14:15:10    

je viens de tomber sur un bug mignon
 

Code :
  1. int main()
  2. {
  3.   unsigned char uc = 0;
  4.   const char &rc(uc);
  5.   uc = 1;
  6.   return rc;
  7. }


 
et non, char c'est ni signed char, ni unsigned char, c'est char. Et avec une const&, ça se traduit par une const& vers une variable temporaire constante :)

Reply

Marsh Posté le 16-11-2005 à 14:15:10   

Reply

Marsh Posté le 16-11-2005 à 14:24:47    

j'ai pas tout compris de ce qui est prouvé ici, mais en tout cas sur mon compilo (vc++7.1) ca compile pas non plus avec des int a la place des char/unsigned char.


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 16-11-2005 à 15:05:52    

bah trouve toi un compilo décent alors. Le code est valide mais ne fait pas forcément ce qu'on croit.

Reply

Marsh Posté le 16-11-2005 à 17:59:57    

bref si ton compilateur compilait, quel serait le résultat ?

Reply

Marsh Posté le 16-11-2005 à 19:41:22    

oui, c'est tout mimi :)
 
la clé, c'est que 'unsigned char' et 'char const' ne sont pas rérérence-compatible, et ne sont pas de class type évidemment.
Donc, comme tu l'as dit, ça entraine la création d'un temporaire via copy initialisation avec conversion standard (lvalue-to-rvalue -> conversion entière -> cv-conversion ). Après la chose amusante, c'est la durée de vie du temporaire, qui est détruit à la fin de la vie de uc.
 
Ce qui est amusant aussi, c'est de compter le nombre de fois ou visual est à la ramasse des qu'on sort des sentiers battus.


Message édité par ++fab le 18-11-2005 à 13:53:31
Reply

Marsh Posté le 17-11-2005 à 10:27:40    

apparement sur g++/gcc 3.2.2 le programme retourne 1 (en tout cas il retourne pas 0
 
[dev@ServeurRH test]$ g++ test.c
[dev@ServeurRH test]$ ./a.out && echo test
[dev@ServeurRH test]$ g++ --version
g++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
 
Si j'ai bien compris, la référence devrait référencer une constante mais pointe sur une valeur qui est ensuite modifiée. Si qq1 pouvait m'expliquer, je comprends déjà pas bien pourquoi ca devrait compiler :(
 
edit : puis a propos de décence de compilo, vc++7.1 n'est pas décent puisqu'il ne compile pas, mais le tien n'est pas décent non plus puisqu'il est buggué, non ?

Message cité 1 fois
Message édité par blackgoddess le 17-11-2005 à 10:29:43

---------------
-( BlackGoddess )-
Reply

Marsh Posté le 17-11-2005 à 10:36:31    

perso je pige pas pkoi un char & pourrait referencer un unsigned char ?

Reply

Marsh Posté le 17-11-2005 à 10:45:29    

blackgoddess a écrit :

Si j'ai bien compris, la référence devrait référencer une constante mais pointe sur une valeur qui est ensuite modifiée. Si qq1 pouvait m'expliquer, je comprends déjà pas bien pourquoi ca devrait compiler :(


qu'est-ce qui ne va pas avec l'explication que j'ai "tenté" de fournir ?
 

blackgoddess a écrit :


edit : puis a propos de décence de compilo, vc++7.1 n'est pas décent puisqu'il ne compile pas, mais le tien n'est pas décent non plus puisqu'il est buggué, non ?


Ce n'est pas un bug, c'est décrit par la norme, 8.5 et 12.2.

Reply

Marsh Posté le 17-11-2005 à 11:08:15    

mmh en relisant une 5ieme fois les explications, il me semble avoir à peu pret compris. J'essaye de décomposer ce que le compilo fait, dites moi si j'ai bien compris svp :)
 

Code :
  1. unsigned char uc = 0;
  2. const char &rc(uc);
  3. =>
  4. unsigned char uc = 0;
  5. const char temp(uc);
  6. const char &rc(temp);


 
mais mon programme compilé ne retourne pas 0, donc j'ai pas du bien comprendre :(


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 18-11-2005 à 14:08:51    

chrisbk a écrit :

perso je pige pas pkoi un char & pourrait referencer un unsigned char ?


 

Code :
  1. void f( unsigned char const& c ){}
  2. void g( unsigned char c ){}
  3. int main()
  4. {
  5.     char c = 'E';
  6.     f( c );
  7.     g( c );
  8. }


 
peut etre pour faire en sorte que f et g aient un comportement voisin (au niveau des conversions appliquées à son argument)
 

Code :
  1. template <class T> void h1( T const& );
  2. template <class T> void h2( T );


 
idem ...

Reply

Marsh Posté le 18-11-2005 à 14:08:51   

Reply

Marsh Posté le 18-11-2005 à 14:14:02    

blackgoddess a écrit :

mmh en relisant une 5ieme fois les explications, il me semble avoir à peu pret compris. J'essaye de décomposer ce que le compilo fait, dites moi si j'ai bien compris svp :)


je suis pas sur à 100%, mais je crois que c'est bon.
 

Citation :

mais mon programme compilé ne retourne pas 0, donc j'ai pas du bien comprendre :(


bug ? ./a.out;echo $? ne retourne pas 0 ?

Reply

Marsh Posté le 18-11-2005 à 14:19:24    

sur g++/gcc 3.2.2
si je compile quelque chose comme :
 

Code :
  1. int main()
  2. {
  3.   return 0;
  4. }


 
puis que je tape : (sur rh)
./a.out && echo test
ca m'affiche test
 
si je compile le code ci-dessus et que je tape la meme commande, je n'obtiens aucun affichage


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 18-11-2005 à 14:29:14    

++fab a écrit :

Code :
  1. void f( unsigned char const& c ){}
  2. void g( unsigned char c ){}
  3. int main()
  4. {
  5.     char c = 'E';
  6.     f( c );
  7.     g( c );
  8. }


 
peut etre pour faire en sorte que f et g aient un comportement voisin (au niveau des conversions appliquées à son argument)
 

Code :
  1. template <class T> void h1( T const& );
  2. template <class T> void h2( T );


 
idem ...


 
heuh ? je te parle de la difference signed / unsigned

Reply

Marsh Posté le 18-11-2005 à 14:47:45    

jte suis pas la ... Regarde le premier message de Taz : signed char != char && unsigned char != char. Après, il y a des conversions standard qui s'appliquent.

Reply

Marsh Posté le 18-11-2005 à 15:56:43    

++fab a écrit :

jte suis pas la ... Regarde le premier message de Taz : signed char != char && unsigned char != char. Après, il y a des conversions standard qui s'appliquent.


 
 

Citation :

#   unsigned char uc = 0;
#
#   const char &rc(uc);


 
Moi ce que je ne comprends pas, c'est qu'une reference sur un "char" puisse porter sur un "unsigned char"
 
jtrouve pas ca logique quoi [:el g]

Reply

Marsh Posté le 18-11-2005 à 16:10:59    

OK, je te redonnes l'exemple qui colle à ce que tu cites :    
 

Code :
  1. void f( char const& c ){}
  2.     void g( char c ){}
  3.  
  4.      int main()
  5.      {
  6.          unsigned char c = 'E';
  7.          f( c );
  8.          g( c );
  9.      }


 
si une référence constante sur un char ne pouvait pas porter sur un unsigned char, f ne permettrait aucune conversion entiere sur son parametre tandis que g oui. Je pense que cette règle a été décidée pour qu'un parametre de type T ou T const& se comporte de meme "à la compilation".

Reply

Marsh Posté le 18-11-2005 à 16:14:56    

mouais [:el g]
 
pas super convaincu

Reply

Marsh Posté le 19-11-2005 à 04:20:35    


Vois que le problème est différent avec signed int qui renvoie la version modifiée (càd l’original), sans créer de temporaire (tout comme char ou int tout court). Tandis que char utilisé comme un type numérique (càd à dire avec un modificateur de type explicite), renvoie la copie de la version originale (un temporaire, exactement comme unsigned int, mais pas signed int, goto 0).
 
Il y a clairement redondance entre ‘int’ et ‘signed int’ (par définition).
Par contre  ‘char’ et ‘signed char’ on des sémantiques différentes.
 
Quel qu'en soit le sens*, l’implémentation est consistante. C’est le plus important (surtout quand on songe aux types qui découlent du modificateur 'unsigned' et aux endroits où ils sont utilisés...)
 
Quant à savoir si le code original est valide, un compilo « décent » dirait sûrement ça :
 
[Warning] Ligne 3 : Variable initialisée avec le type int ; j’attendais un unsigned char
[Warning] Ligne 5 : création d’un temporaire
[Warning] Ligne 5 : initialisation d'une référence (constante) sur un char à partir d'un type modifié
[Warning] Ligne 7 : Assignation d'un int à un unsigned char
[Warning] Ligne 8 : La fonction retourne un int, je trouve une référence (constante) sur un char
 
5 Warnings.
 
/*const */ char &a=*"+";

Reply

Marsh Posté le 19-11-2005 à 13:56:13    

fra0 a écrit :

Vois que le problème est différent avec signed int qui renvoie la version modifiée (càd l’original), sans créer de temporaire (tout comme char ou int tout court). Tandis que char utilisé comme un type numérique (càd à dire avec un modificateur de type explicite), renvoie la copie de la version originale (un temporaire, exactement comme unsigned int, mais pas signed int, goto 0).
 
Il y a clairement redondance entre ‘int’ et ‘signed int’ (par définition).
Par contre  ‘char’ et ‘signed char’ on des sémantiques différentes.


 
oui, signed int const est reference-compatible avec int, alors que signed char const n'est pas référence-compatible avec char.
 

fra0 a écrit :


Quant à savoir si le code original est valide, un compilo « décent » dirait sûrement ça :
 
[Warning] Ligne 3 : Variable initialisée avec le type int ; j’attendais un unsigned char
[Warning] Ligne 5 : création d’un temporaire
[Warning] Ligne 5 : initialisation d'une référence (constante) sur un char à partir d'un type modifié
[Warning] Ligne 7 : Assignation d'un int à un unsigned char
[Warning] Ligne 8 : La fonction retourne un int, je trouve une référence (constante) sur un char


 
avec l'option -Wpedantic-with-the-little-finger-up ? :)

Reply

Marsh Posté le 21-11-2005 à 14:36:29    

Vive le typage fort !
Cela peut être parfois un peu lourd mais en tout cas on fait des programmes cohérents.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed