J'ai perdu des heures à chasser un bug stupide du style
std::string bad='x'+"yz"; // donne tout sauf "xyz"
("yz" était en fait le résultat d'une conversion genre class::operator
char*() ...)
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à la C ?
J'ai essayé de définir un operator+(const char lhs, const char* rhs) qui
râlerait, mais VC 7.1 dit qu'une des deux opérandes doit être une classe...
--
Philippe Guglielmetti - www.dynabits.com
Si je ne me trompe pas, le résultat est un char const *, pointant à l'adresse de "yz" augmentée de la valeur entière 'x'.
Et rien n'empêche un compilo de servir un café au lait, puisqu'il s'agit d'un comportement indéfini.
-- ;-)
drkm
Fabien LE LEZ writes:
On Thu, 19 Aug 2004 18:45:36 +0200, drkm :
Si je ne me trompe pas, le résultat est un char const *, pointant à l'adresse de "yz" augmentée de la valeur entière 'x'.
Et rien n'empêche un compilo de servir un café au lait, puisqu'il s'agit d'un comportement indéfini.
Le problème est qu'il peut également te le servir avec du sel en guise de sucre, ce qui le fait moins bien passer ;-)
Mais si je comprend bien, le comportement indéfini vient du fait que l'on sort des bornes du tableau (et du « one past the end »). Mais ceci aurait le résultat escompté :
char c = 5 ; std::string s = c + "12345xyz" ;
Non ?
--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html
Fabien LE LEZ <gramster@gramster.com> writes:
On Thu, 19 Aug 2004 18:45:36 +0200, drkm <usenet.fclcxx@fgeorges.org>:
Si je ne me trompe pas, le résultat est un char const *, pointant à
l'adresse de "yz" augmentée de la valeur entière 'x'.
Et rien n'empêche un compilo de servir un café au lait, puisqu'il
s'agit d'un comportement indéfini.
Le problème est qu'il peut également te le servir avec du sel en
guise de sucre, ce qui le fait moins bien passer ;-)
Mais si je comprend bien, le comportement indéfini vient du fait que
l'on sort des bornes du tableau (et du « one past the end »). Mais
ceci aurait le résultat escompté :
char c = 5 ;
std::string s = c + "12345xyz" ;
Non ?
--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html
Si je ne me trompe pas, le résultat est un char const *, pointant à l'adresse de "yz" augmentée de la valeur entière 'x'.
Et rien n'empêche un compilo de servir un café au lait, puisqu'il s'agit d'un comportement indéfini.
Le problème est qu'il peut également te le servir avec du sel en guise de sucre, ce qui le fait moins bien passer ;-)
Mais si je comprend bien, le comportement indéfini vient du fait que l'on sort des bornes du tableau (et du « one past the end »). Mais ceci aurait le résultat escompté :
char c = 5 ; std::string s = c + "12345xyz" ;
Non ?
--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html
Fabien LE LEZ
On Thu, 19 Aug 2004 19:31:20 +0200, drkm :
Le problème est qu'il peut également te le servir avec du sel en guise de sucre, ce qui le fait moins bien passer ;-)
De toutes façons, je déteste le café, qu'il soit sucré ou salé. Même avec des frites.
Mais si je comprend bien, le comportement indéfini vient du fait que l'on sort des bornes du tableau (et du « one past the end »).
Oui.
Mais ceci aurait le résultat escompté :
char c = 5 ; std::string s = c + "12345xyz" ;
"Escompté" ne me paraît pas convenir ici -- le résultat "logique" serait "512345xyz". Mais le fait est que ce code met bien "xyz" dans s.
-- ;-)
On Thu, 19 Aug 2004 19:31:20 +0200, drkm <usenet.fclcxx@fgeorges.org>:
Le problème est qu'il peut également te le servir avec du sel en
guise de sucre, ce qui le fait moins bien passer ;-)
De toutes façons, je déteste le café, qu'il soit sucré ou salé. Même
avec des frites.
Mais si je comprend bien, le comportement indéfini vient du fait que
l'on sort des bornes du tableau (et du « one past the end »).
Oui.
Mais
ceci aurait le résultat escompté :
char c = 5 ;
std::string s = c + "12345xyz" ;
"Escompté" ne me paraît pas convenir ici -- le résultat "logique"
serait "512345xyz". Mais le fait est que ce code met bien "xyz" dans
s.
Le problème est qu'il peut également te le servir avec du sel en guise de sucre, ce qui le fait moins bien passer ;-)
De toutes façons, je déteste le café, qu'il soit sucré ou salé. Même avec des frites.
Mais si je comprend bien, le comportement indéfini vient du fait que l'on sort des bornes du tableau (et du « one past the end »).
Oui.
Mais ceci aurait le résultat escompté :
char c = 5 ; std::string s = c + "12345xyz" ;
"Escompté" ne me paraît pas convenir ici -- le résultat "logique" serait "512345xyz". Mais le fait est que ce code met bien "xyz" dans s.
-- ;-)
drkm
Fabien LE LEZ writes:
On Thu, 19 Aug 2004 19:31:20 +0200, drkm :
Mais ceci aurait le résultat escompté :
char c = 5 ; std::string s = c + "12345xyz" ;
"Escompté" ne me paraît pas convenir ici -- le résultat "logique" serait "512345xyz". Mais le fait est que ce code met bien "xyz" dans s.
Lorsque je disais « escompté », je me référais à l'exemple du PO et au résultat qu'il pensait obtenir.
Je ne sais pas s'il y a un résultat plus logique que l'autre. Si l'on suppose que l'auteur des deux lignes de code ci-dessus connait son affaire, je pense que le résultat /escompté/ est bien "xyz".
Mais il est vrai qu'a priori, si je vois ces mêmes lignes de code, je ne dirais pas que son auteur connait son affaire.
--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html
Fabien LE LEZ <gramster@gramster.com> writes:
On Thu, 19 Aug 2004 19:31:20 +0200, drkm <usenet.fclcxx@fgeorges.org>:
Mais ceci aurait le résultat escompté :
char c = 5 ;
std::string s = c + "12345xyz" ;
"Escompté" ne me paraît pas convenir ici -- le résultat "logique"
serait "512345xyz". Mais le fait est que ce code met bien "xyz" dans
s.
Lorsque je disais « escompté », je me référais à l'exemple du PO et
au résultat qu'il pensait obtenir.
Je ne sais pas s'il y a un résultat plus logique que l'autre. Si
l'on suppose que l'auteur des deux lignes de code ci-dessus connait
son affaire, je pense que le résultat /escompté/ est bien "xyz".
Mais il est vrai qu'a priori, si je vois ces mêmes lignes de code,
je ne dirais pas que son auteur connait son affaire.
--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html
"Escompté" ne me paraît pas convenir ici -- le résultat "logique" serait "512345xyz". Mais le fait est que ce code met bien "xyz" dans s.
Lorsque je disais « escompté », je me référais à l'exemple du PO et au résultat qu'il pensait obtenir.
Je ne sais pas s'il y a un résultat plus logique que l'autre. Si l'on suppose que l'auteur des deux lignes de code ci-dessus connait son affaire, je pense que le résultat /escompté/ est bien "xyz".
Mais il est vrai qu'a priori, si je vois ces mêmes lignes de code, je ne dirais pas que son auteur connait son affaire.
--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html
Fabien LE LEZ
On Thu, 19 Aug 2004 21:47:26 +0200, drkm :
Je ne sais pas s'il y a un résultat plus logique que l'autre. Si l'on suppose que l'auteur des deux lignes de code ci-dessus connait son affaire,
Peut-être. Je pense au pauvre relecteur qui essaie de décrypter le code de l'auteur en question.
je pense que le résultat /escompté/ est bien "xyz".
Pour moi, operator + (..., char const*) devrait faire de la concaténation -- surtout si l'autre argument est un char.
me semble à la limite de l'obfuscation -- généralement, un indice devrait plutôt être un int.
-- ;-)
Philippe Guglielmetti
merci à tous pour vos réponses. J'étais bien conscient que 'x' + "yz" fait de l'arithmétique de pointeurs.
A mon avis, il est anormal que char soit considéré comme un (short) int sans le moindre warning. Tout comme bool, char et wchar_t ne devraient pas être des intégraux, du moins pas sans conversion explicite.
J'ai toujours milité pour que C++ soit considéré comme un langage moderne, très différent de C, mais là y'a encore du boulot... -- Philippe Guglielmetti - www.dynabits.com
merci à tous pour vos réponses.
J'étais bien conscient que 'x' + "yz" fait de l'arithmétique de pointeurs.
A mon avis, il est anormal que char soit considéré comme un (short) int sans
le moindre warning.
Tout comme bool, char et wchar_t ne devraient pas être des intégraux, du
moins pas sans conversion explicite.
J'ai toujours milité pour que C++ soit considéré comme un langage moderne,
très différent de C, mais là y'a encore du boulot...
--
Philippe Guglielmetti - www.dynabits.com
merci à tous pour vos réponses. J'étais bien conscient que 'x' + "yz" fait de l'arithmétique de pointeurs.
A mon avis, il est anormal que char soit considéré comme un (short) int sans le moindre warning. Tout comme bool, char et wchar_t ne devraient pas être des intégraux, du moins pas sans conversion explicite.
J'ai toujours milité pour que C++ soit considéré comme un langage moderne, très différent de C, mais là y'a encore du boulot... -- Philippe Guglielmetti - www.dynabits.com
kanze
Falk Tannhäuser wrote in message news:<cg2lso$tee$...
Fabien LE LEZ wrote:
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à la C ?
A priori, non. Mais il n'est pas impossible que certains compilos génèrent un warning (modulo l'option qui va bien).
Avec 'gcc -Wall', j'ai bien un warning "array subscript has type `char'" quand je fais std::string bad = &'x'["yz"]; (qui est fonctionellement équivalent à std::string bad = 'x' + "yz"; mais il me ne semble pas avoir de moyen pour faire générer un warning dans ce cas)
On pourrait générer un avertissement chaque fois que le programmeur essaie d'utiliser un char comme un petit entier:-). Le problème alors sera, comment trouver les avertissements « intéressants » parmi l'inondation.
Dans ce cas particulier, l'arithmétique ne comporte que des constantes (un pointeur constant et un entier constant). Or, tous les compilateurs que je connais font du « constant folding », c-à-d qu'ils évaluent l'expression lors de la compilation, et non à l'exécution. C'est un peu plus complex quand il y a un pointeur, évidemment, parce que constante ou non, l'adresse exacte finale n'est pas connue du compilateur. Mais le compilateur doit pouvoir détecter que le pointeur qui résulte de 'x' + "yz" ne peut pas être valide, en aucun cas, et réfuser à compiler le code. Je ne connais pas la structure interne de g++, mais j'imagine qu'il serait même assez simple d'ajouter ce genre de vérification.
Ceci dit, est-ce que ce genre d'erreur est assez fréquente pour qu'ils investissent l'effort nécessaire pour le détecter ?
Ce sont les joies de l'arithmétique des pointeurs combiné aux règles loufoques de conversion tableau => pointeur, qui font que le code en question *doit* être accepté par le compilateur, bien qu'il produise un comportement indéfini.
Dans le cas général, tu as raison. Dans ce cas précis, en revanche, le code a un comportement indéfini -- on génère un pointeur invalid, et le compilateur a le droit même de ne pas le compiler.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Falk Tannhäuser <falk.tannhauser@crf.canon.fr> wrote in message
news:<cg2lso$tee$1@s5.feed.news.oleane.net>...
Fabien LE LEZ wrote:
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à
la C ?
A priori, non. Mais il n'est pas impossible que certains compilos
génèrent un warning (modulo l'option qui va bien).
Avec 'gcc -Wall', j'ai bien un warning "array subscript has type `char'"
quand je fais
std::string bad = &'x'["yz"];
(qui est fonctionellement équivalent à
std::string bad = 'x' + "yz";
mais il me ne semble pas avoir de moyen pour faire générer un
warning dans ce cas)
On pourrait générer un avertissement chaque fois que le programmeur
essaie d'utiliser un char comme un petit entier:-). Le problème alors
sera, comment trouver les avertissements « intéressants » parmi
l'inondation.
Dans ce cas particulier, l'arithmétique ne comporte que des constantes
(un pointeur constant et un entier constant). Or, tous les compilateurs
que je connais font du « constant folding », c-à-d qu'ils évaluent
l'expression lors de la compilation, et non à l'exécution. C'est un peu
plus complex quand il y a un pointeur, évidemment, parce que constante
ou non, l'adresse exacte finale n'est pas connue du compilateur. Mais le
compilateur doit pouvoir détecter que le pointeur qui résulte de 'x' +
"yz" ne peut pas être valide, en aucun cas, et réfuser à compiler le
code. Je ne connais pas la structure interne de g++, mais j'imagine
qu'il serait même assez simple d'ajouter ce genre de vérification.
Ceci dit, est-ce que ce genre d'erreur est assez fréquente pour qu'ils
investissent l'effort nécessaire pour le détecter ?
Ce sont les joies de l'arithmétique des pointeurs combiné aux règles
loufoques de conversion tableau => pointeur, qui font que le code en
question *doit* être accepté par le compilateur, bien qu'il produise
un comportement indéfini.
Dans le cas général, tu as raison. Dans ce cas précis, en revanche, le
code a un comportement indéfini -- on génère un pointeur invalid, et le
compilateur a le droit même de ne pas le compiler.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Falk Tannhäuser wrote in message news:<cg2lso$tee$...
Fabien LE LEZ wrote:
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à la C ?
A priori, non. Mais il n'est pas impossible que certains compilos génèrent un warning (modulo l'option qui va bien).
Avec 'gcc -Wall', j'ai bien un warning "array subscript has type `char'" quand je fais std::string bad = &'x'["yz"]; (qui est fonctionellement équivalent à std::string bad = 'x' + "yz"; mais il me ne semble pas avoir de moyen pour faire générer un warning dans ce cas)
On pourrait générer un avertissement chaque fois que le programmeur essaie d'utiliser un char comme un petit entier:-). Le problème alors sera, comment trouver les avertissements « intéressants » parmi l'inondation.
Dans ce cas particulier, l'arithmétique ne comporte que des constantes (un pointeur constant et un entier constant). Or, tous les compilateurs que je connais font du « constant folding », c-à-d qu'ils évaluent l'expression lors de la compilation, et non à l'exécution. C'est un peu plus complex quand il y a un pointeur, évidemment, parce que constante ou non, l'adresse exacte finale n'est pas connue du compilateur. Mais le compilateur doit pouvoir détecter que le pointeur qui résulte de 'x' + "yz" ne peut pas être valide, en aucun cas, et réfuser à compiler le code. Je ne connais pas la structure interne de g++, mais j'imagine qu'il serait même assez simple d'ajouter ce genre de vérification.
Ceci dit, est-ce que ce genre d'erreur est assez fréquente pour qu'ils investissent l'effort nécessaire pour le détecter ?
Ce sont les joies de l'arithmétique des pointeurs combiné aux règles loufoques de conversion tableau => pointeur, qui font que le code en question *doit* être accepté par le compilateur, bien qu'il produise un comportement indéfini.
Dans le cas général, tu as raison. Dans ce cas précis, en revanche, le code a un comportement indéfini -- on génère un pointeur invalid, et le compilateur a le droit même de ne pas le compiler.
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
kanze
"Philippe Guglielmetti" wrote in message news:<41259cbb$0$2796$...
A mon avis, il est anormal que char soit considéré comme un (short) int sans le moindre warning. Tout comme bool, char et wchar_t ne devraient pas être des intégraux, du moins pas sans conversion explicite.
Et qu'est-ce qu'ils doivent être, alors ? Il faut bien, comme minimum, que je puisse utiliser des char comme index dans un tableau. Y compris un tableau de bits, ce qui impose au moins les opérateurs %, /, >> et <<.
(Je ne trouve pas que la situation actuelle est optimal, mais je n'ai pas vu de propositions qui l'aurait fait mieux.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Philippe Guglielmetti" <news@dynabits.com> wrote in message
news:<41259cbb$0$2796$5402220f@news.sunrise.ch>...
A mon avis, il est anormal que char soit considéré comme un (short)
int sans le moindre warning. Tout comme bool, char et wchar_t ne
devraient pas être des intégraux, du moins pas sans conversion
explicite.
Et qu'est-ce qu'ils doivent être, alors ? Il faut bien, comme minimum,
que je puisse utiliser des char comme index dans un tableau. Y compris
un tableau de bits, ce qui impose au moins les opérateurs %, /, >> et
<<.
(Je ne trouve pas que la situation actuelle est optimal, mais je n'ai
pas vu de propositions qui l'aurait fait mieux.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Philippe Guglielmetti" wrote in message news:<41259cbb$0$2796$...
A mon avis, il est anormal que char soit considéré comme un (short) int sans le moindre warning. Tout comme bool, char et wchar_t ne devraient pas être des intégraux, du moins pas sans conversion explicite.
Et qu'est-ce qu'ils doivent être, alors ? Il faut bien, comme minimum, que je puisse utiliser des char comme index dans un tableau. Y compris un tableau de bits, ce qui impose au moins les opérateurs %, /, >> et <<.
(Je ne trouve pas que la situation actuelle est optimal, mais je n'ai pas vu de propositions qui l'aurait fait mieux.)
-- James Kanze GABI Software http://www.gabi-soft.fr Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Pierre Maurette
a écrit:
Falk Tannhäuser wrote in message news:<cg2lso$tee$...
Fabien LE LEZ wrote:
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à la C ?
A priori, non. Mais il n'est pas impossible que certains compilos génèrent un warning (modulo l'option qui va bien).
Avec 'gcc -Wall', j'ai bien un warning "array subscript has type `char'" quand je fais std::string bad = &'x'["yz"]; (qui est fonctionellement équivalent à std::string bad = 'x' + "yz"; mais il me ne semble pas avoir de moyen pour faire générer un warning dans ce cas)
On pourrait générer un avertissement chaque fois que le programmeur essaie d'utiliser un char comme un petit entier:-). Le problème alors sera, comment trouver les avertissements « intéressants » parmi l'inondation. 1: const char offset_nom = sizeof("Pierre");// / sizeof(char);
Tout ça sans ouharning (gcc 3.3.1, -Wall, et VC7.1).
Si l'on considère que tous mes compilos me préviennent quand je fais: if(ptr = fonction_qui_renvoie_un_pointeur()){...} et logiquement se taisent avec: if((ptr = fonction_qui_renvoie_un_pointeur()) != NULL){...} le ligne 2 sent également la faute de frappe ou l'erreur de débutant à plein nez. Elle mériterait un warning. En fait, je préfèrerais une classe string qui refuse la ligne 2 et qui accepte: NouvelleString pluriel_debile = "Automobile" + "s";
La ligne 3 me convient parfaitement. Alors que je me demandais si elle était légale ;-)
La ligne 4 est à mon sens débile. Il faudrait au moins avertir (même dans ce cas, où le compilo peut savoir que rien de fâcheux ne va se passer). Si l'on veut faire du C, les classes string ont prévu ce qu'il faut (ligne 5).
Et ce qui me déçoit, c'est que l'AnsiString de la VCL Borland a le même comportement que std::string sur ce point. En revanche, Delphi et la même VCL autorisent logiquement:
var Test: AnsiString; begin Test := 'Pierre '+ 'Maurette';
La différence est facilement explicable, mais c'est chiant.
Dans ce cas particulier, l'arithmétique ne comporte que des constantes (un pointeur constant et un entier constant). Or, tous les compilateurs que je connais font du « constant folding », c-à-d qu'ils évaluent l'expression lors de la compilation, et non à l'exécution. C'est un peu plus complex quand il y a un pointeur, évidemment, parce que constante ou non, l'adresse exacte finale n'est pas connue du compilateur. Oui. Je pense que le compilateur connaît toutes les adresses des
données initialisées (ou même non initialisées) au pire à une constante près, déterminée par le lieur puis le chargeur. On peut donc affirmer qu'il a tous les éléments nécessaires et le programmeur peut considérer ces adresses comme des constantes connues à la compilation. int* ptr = &MaVar; génère un truc du genre de ce qu'on peut faire directement en assembleur: mov eax, offset MaVar offset MaVar est une constante immédiate, en tous cas se retrouvera sous cette forme dans l'executable en mémoire (pas nécessairement dans le point exe sur le disque). Et il me semble que sur les archis que je connais (en fait, une seule, ou à peu près :-() les choses sont encore plus simples, le travail du lieur et du chargeur se réduit à positionner la valeur de segments ou leurs descripteurs. Ainsi, le compilateur connait les valeurs numériques des offset, c'est à dire des adresses. -- Pierre
kanze@gabi-soft.fr a écrit:
Falk Tannhäuser <falk.tannhauser@crf.canon.fr> wrote in message
news:<cg2lso$tee$1@s5.feed.news.oleane.net>...
Fabien LE LEZ wrote:
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à
la C ?
A priori, non. Mais il n'est pas impossible que certains compilos
génèrent un warning (modulo l'option qui va bien).
Avec 'gcc -Wall', j'ai bien un warning "array subscript has type `char'"
quand je fais
std::string bad = &'x'["yz"];
(qui est fonctionellement équivalent à
std::string bad = 'x' + "yz";
mais il me ne semble pas avoir de moyen pour faire générer un
warning dans ce cas)
On pourrait générer un avertissement chaque fois que le programmeur
essaie d'utiliser un char comme un petit entier:-). Le problème alors
sera, comment trouver les avertissements « intéressants » parmi
l'inondation.
1: const char offset_nom = sizeof("Pierre");// / sizeof(char);
Tout ça sans ouharning (gcc 3.3.1, -Wall, et VC7.1).
Si l'on considère que tous mes compilos me préviennent quand je fais:
if(ptr = fonction_qui_renvoie_un_pointeur()){...}
et logiquement se taisent avec:
if((ptr = fonction_qui_renvoie_un_pointeur()) != NULL){...}
le ligne 2 sent également la faute de frappe ou l'erreur de débutant à
plein nez. Elle mériterait un warning. En fait, je préfèrerais une
classe string qui refuse la ligne 2 et qui accepte:
NouvelleString pluriel_debile = "Automobile" + "s";
La ligne 3 me convient parfaitement. Alors que je me demandais si elle
était légale ;-)
La ligne 4 est à mon sens débile. Il faudrait au moins avertir (même
dans ce cas, où le compilo peut savoir que rien de fâcheux ne va se
passer). Si l'on veut faire du C, les classes string ont prévu ce
qu'il faut (ligne 5).
Et ce qui me déçoit, c'est que l'AnsiString de la VCL Borland a le
même comportement que std::string sur ce point. En revanche, Delphi et
la même VCL autorisent logiquement:
var
Test: AnsiString;
begin
Test := 'Pierre '+ 'Maurette';
La différence est facilement explicable, mais c'est chiant.
Dans ce cas particulier, l'arithmétique ne comporte que des constantes
(un pointeur constant et un entier constant). Or, tous les compilateurs
que je connais font du « constant folding », c-à-d qu'ils évaluent
l'expression lors de la compilation, et non à l'exécution. C'est un peu
plus complex quand il y a un pointeur, évidemment, parce que constante
ou non, l'adresse exacte finale n'est pas connue du compilateur.
Oui. Je pense que le compilateur connaît toutes les adresses des
données initialisées (ou même non initialisées) au pire à une
constante près, déterminée par le lieur puis le chargeur. On peut donc
affirmer qu'il a tous les éléments nécessaires et le programmeur peut
considérer ces adresses comme des constantes connues à la compilation.
int* ptr = &MaVar;
génère un truc du genre de ce qu'on peut faire directement en
assembleur:
mov eax, offset MaVar
offset MaVar est une constante immédiate, en tous cas se retrouvera
sous cette forme dans l'executable en mémoire (pas nécessairement dans
le point exe sur le disque).
Et il me semble que sur les archis que je connais (en fait, une seule,
ou à peu près :-() les choses sont encore plus simples, le travail du
lieur et du chargeur se réduit à positionner la valeur de segments ou
leurs descripteurs. Ainsi, le compilateur connait les valeurs
numériques des offset, c'est à dire des adresses.
--
Pierre
Falk Tannhäuser wrote in message news:<cg2lso$tee$...
Fabien LE LEZ wrote:
Existe-t-il une combine pour empêcher C++ de compiler des bêtises à la C ?
A priori, non. Mais il n'est pas impossible que certains compilos génèrent un warning (modulo l'option qui va bien).
Avec 'gcc -Wall', j'ai bien un warning "array subscript has type `char'" quand je fais std::string bad = &'x'["yz"]; (qui est fonctionellement équivalent à std::string bad = 'x' + "yz"; mais il me ne semble pas avoir de moyen pour faire générer un warning dans ce cas)
On pourrait générer un avertissement chaque fois que le programmeur essaie d'utiliser un char comme un petit entier:-). Le problème alors sera, comment trouver les avertissements « intéressants » parmi l'inondation. 1: const char offset_nom = sizeof("Pierre");// / sizeof(char);
Tout ça sans ouharning (gcc 3.3.1, -Wall, et VC7.1).
Si l'on considère que tous mes compilos me préviennent quand je fais: if(ptr = fonction_qui_renvoie_un_pointeur()){...} et logiquement se taisent avec: if((ptr = fonction_qui_renvoie_un_pointeur()) != NULL){...} le ligne 2 sent également la faute de frappe ou l'erreur de débutant à plein nez. Elle mériterait un warning. En fait, je préfèrerais une classe string qui refuse la ligne 2 et qui accepte: NouvelleString pluriel_debile = "Automobile" + "s";
La ligne 3 me convient parfaitement. Alors que je me demandais si elle était légale ;-)
La ligne 4 est à mon sens débile. Il faudrait au moins avertir (même dans ce cas, où le compilo peut savoir que rien de fâcheux ne va se passer). Si l'on veut faire du C, les classes string ont prévu ce qu'il faut (ligne 5).
Et ce qui me déçoit, c'est que l'AnsiString de la VCL Borland a le même comportement que std::string sur ce point. En revanche, Delphi et la même VCL autorisent logiquement:
var Test: AnsiString; begin Test := 'Pierre '+ 'Maurette';
La différence est facilement explicable, mais c'est chiant.
Dans ce cas particulier, l'arithmétique ne comporte que des constantes (un pointeur constant et un entier constant). Or, tous les compilateurs que je connais font du « constant folding », c-à-d qu'ils évaluent l'expression lors de la compilation, et non à l'exécution. C'est un peu plus complex quand il y a un pointeur, évidemment, parce que constante ou non, l'adresse exacte finale n'est pas connue du compilateur. Oui. Je pense que le compilateur connaît toutes les adresses des
données initialisées (ou même non initialisées) au pire à une constante près, déterminée par le lieur puis le chargeur. On peut donc affirmer qu'il a tous les éléments nécessaires et le programmeur peut considérer ces adresses comme des constantes connues à la compilation. int* ptr = &MaVar; génère un truc du genre de ce qu'on peut faire directement en assembleur: mov eax, offset MaVar offset MaVar est une constante immédiate, en tous cas se retrouvera sous cette forme dans l'executable en mémoire (pas nécessairement dans le point exe sur le disque). Et il me semble que sur les archis que je connais (en fait, une seule, ou à peu près :-() les choses sont encore plus simples, le travail du lieur et du chargeur se réduit à positionner la valeur de segments ou leurs descripteurs. Ainsi, le compilateur connait les valeurs numériques des offset, c'est à dire des adresses. -- Pierre
Philippe Guglielmetti
a écrit:
Il faut bien, comme minimum, que je puisse utiliser des char comme index dans un tableau.
Pourquoi faire? c'est hyper dangereux! Tu penses comme un C-iste pour qui il y a un "typedef unsigned short int char;" quelque part... AMHA (à mon humble avis...), tableau['x'] devrait être interdit en C++, surtout depuis que 'é' n'a pas la même valeur selon les OS, et encore plus depuis Unicode. Le bidouilleur nostalgique peut toujours faire tableau[(unsigned short)'x'] -- Philippe Guglielmetti - www.dynabits.com
<kanze@gabi-soft.fr> a écrit:
Il faut bien, comme minimum,
que je puisse utiliser des char comme index dans un tableau.
Pourquoi faire? c'est hyper dangereux!
Tu penses comme un C-iste pour qui il y a un "typedef unsigned short int
char;" quelque part...
AMHA (à mon humble avis...), tableau['x'] devrait être interdit en C++,
surtout depuis que 'é'
n'a pas la même valeur selon les OS, et encore plus depuis Unicode.
Le bidouilleur nostalgique peut toujours faire tableau[(unsigned short)'x']
--
Philippe Guglielmetti - www.dynabits.com
Il faut bien, comme minimum, que je puisse utiliser des char comme index dans un tableau.
Pourquoi faire? c'est hyper dangereux! Tu penses comme un C-iste pour qui il y a un "typedef unsigned short int char;" quelque part... AMHA (à mon humble avis...), tableau['x'] devrait être interdit en C++, surtout depuis que 'é' n'a pas la même valeur selon les OS, et encore plus depuis Unicode. Le bidouilleur nostalgique peut toujours faire tableau[(unsigned short)'x'] -- Philippe Guglielmetti - www.dynabits.com