OVH Cloud OVH Cloud

empêcher la compilation de 'x'+"yz" ?

50 réponses
Avatar
Philippe Guglielmetti
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

10 réponses

1 2 3 4 5
Avatar
Fabien LE LEZ
On 23 Aug 2004 01:58:41 -0700, :

Et c'est quelque chose de tellement fondamental dans le
langage que je ne le vois pas changer, jamais.


Ne t'inquiète pas, d'ici quelques mois, tout le monde se sera mis à C#
et le C++ sera totalement abandonné. Aussi, le problème ne se posera
plus.


--
;-)

Avatar
kanze
"Michel Michaud" wrote in message
news:<iM8Wc.6741$...
Dans news:,
Un autre cas, en passant... Comment est-ce que tu écriras une
fonction d'hachage sans l'arithmétique sur des char's ?


Manques-tu d'imagination à ce point ? Avec quelque chose du genre de

const string MES_LETTRES= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcd ... etc. "
"ÀÈÌÒÙàèìòùÂÊÎÔÛâê ... etc."
" ... etc. ";

je pourrai même choisir la valeur numérique associée à chaque lettre c
et obtenue par MES_LETTRES.find(c) !

Tu peux faire la même chose pour l'ensemble des caractères
au besoin...


Si tu fais une table hachée sur std::string, c'est ce qu'il te faut.

Mais tu ne trouves pas que c'est d'ajouter la complexité pour rien ?
ORD(ch) marche aussi bien, non ? Et c'est plus rapide. (Comme quoi, même
Pascal en reconnaissait le besoin.:-))

--
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


Avatar
Pierre Maurette
a écrit:

Pierre Maurette wrote in message
[...]

La différence est simple, et n'a rien à voir avec la bibliothèque. En
[...]

La différence est facilement explicable, mais c'est chiant.
Nous sommes d'accord sur pratiquement tous les points. Je trouve


simplement certains choix du langage C++ "regrettables". Loin de moi
l'idée de les refuser ;-), j'en admets l'origine historique. Il est
clair que ce n'est pas par l'écriture d'une classe qu'il sera possible
de modifier l'évaluation de la donnée de droite (celle passée au
constructeur).
Je regrette l'absence de warning sur des pièges évidents, mais le C++
assume si bien son coté piégeux.
Je trouve dommage qu'au même endroit (initialisation d'une string), le
signe + puisse signifier des choses aussi différentes qu'une
concaténation et un déplacement dans la mémoire.
Je suis d'accord que la signification de cet opérateur n'est pas
ambiguë, pour peu que l'on connaisse le langage (lequel?). Je ferai
simplement une remarque: il existe un débat récurrent sur ce forum
concernant l'utilité de la connaissance du langage C pour un
programemur C++, l'opinion des membres le plus actifs semblant être
que cette influence est néfaste. Hors, nous pouvons constater ici que
les mécanismes intellectuels qui amènent à interprêter, prévoir, ce
qui se passe avant l'appel du constructeur sont typiquement du C, et
d'un bon niveau.

[...]
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.


Faute d'en connaître l'adresse, il en connaît la longueur. Il sait donc
qu'ajouter tant à l'adresse déborde.

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.


Pas forcement. En fait, plutôt rarement. D'abord, évidemment, parce
qu'il y a beaucoup de systèmes sans ségments. Puis, aujourd'hui, la
plupart des systèmes sur Intel (Windows, Unix) ont choisi d'ignorer les
segments, en limitant l'adressage aux 32 bits de l'offset. Et enfin,
même avant, il était courant de mettre des variables de plusieurs unités
de compilation différentes dans le même segment.

Mais le compilateur n'a pas besoin de connaître l'adresse exacte. Il
sait que des adresses dans l'intervale [adresse,adresse+n[ sont valide,
et que seulement ces adresses sont valide. Si dans le code, je fais
adresse+i, avec i>n, il sait que l'expression n'est pas valide.
<HS>

Je précise bien que je ne me base que sur un seul environnement. Et en
fait, sur un assembleur, MASM (ou clône), qui permet de bien
appréhender la tuyauterie. Mais c'est tout à fait portable sur un
compilateur C++ du même environnement.
MASM est un vieux truc, qui réussit l'exploit d'utiliser le même mot
"segment" pour désigner des zones définies par le programmeur
(essentiellement par leurs attributs) et les segments physiques,
eux-mêmes réels ou virtuels, en simplifiant beaucoup.
Sous Windows, la notion de segment existe quand même au minimum en
termes de droits, entre le code, les données et la pile.
J'ai eu à expliquer que l'adresse d'une variable est une constante
symbolique connue à la compilation, ce n'est pas absolument immédiat.
En d'autres termes que dans:
mov bx, @data
mov cx, offset VALEUR
"@data" et "offset VALEUR" SONT (et non pas ressemblent à) des valeurs
immédiates.
</HS>
--
Pierre


Avatar
Samuel Krempp
le Sunday 22 August 2004 19:35, écrivit :

"Philippe Guglielmetti" writes:

|> a écrit:
|> > Il faut bien, comme minimum,
|> > que je puisse utiliser des char comme index dans un tableau.

|> Pourquoi faire?

Implémenter <ctype.h> pour commencer. Ou quelque chose de semblable,
avec ses propres classifications.

|> c'est hyper dangereux!

Utiliser le C++, c'est hyper dangéreux. Je ne vois pas pourquoi quelque
chose du genre « table[ ch - CHAR_MIN ] » serait plus dangéreux que
d'autre chose.


Quand on soustrait 2 chars, on obtient un char, non ?
Alors j'imagine que ce CHAR_MIN est de type int (ou en tout cas qque chose
qui a au moins autant de valeurs positives que char n'a de valeurs
différentes en tout).
Au début je pensais que tu voulais dire utiliser un char *directement* comme
indice dans un tableau, alors que visiblement tu veux juste pouvoir obtenir
un indice à partir d'un char. Et ça je peux comprendre que ça puisse
servir.

J'ai l'impression qu'on a besoin de rien de plus que de pouvoir faire un
entier en soustrayant 2 chars (un peu comme pour des pointeurs) et de
connaître "le premier char".
Si on avait ça et un type char qui n'est pas intrinsèquement un type
intégral, je pense que ça éviterait pas mal de pièges possibles sans
empêcher quoi que ce soit d'utile.

--
Sam

Avatar
Michel Michaud
Dans news:,
"Michel Michaud" wrote in message
news:<iM8Wc.6741$...
Manques-tu d'imagination à ce point ? Avec quelque chose du
genre de

const string MES_LETTRES= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcd ... etc. "
"ÀÈÌÒÙàèìòùÂÊÎÔÛâê ... etc."
" ... etc. ";

je pourrai même choisir la valeur numérique associée à chaque
lettre c et obtenue par MES_LETTRES.find(c) !
[...]


Mais tu ne trouves pas que c'est d'ajouter la complexité pour
rien ? ORD(ch) marche aussi bien, non ? Et c'est plus rapide.
(Comme quoi, même Pascal en reconnaissait le besoin.:-))


C++ aussi permet de convertir ! On parlait seulement du fait
d'enlever cette conversion et tu croyais que ce serait
dramatique. Je dirais simplement que ce serait moins commode.

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Avatar
Gabriel Dos Reis
Samuel Krempp writes:

| le Sunday 22 August 2004 19:35, écrivit :
|
| > "Philippe Guglielmetti" writes:
| >
| > |> a écrit:
| > |> > Il faut bien, comme minimum,
| > |> > que je puisse utiliser des char comme index dans un tableau.
| >
| > |> Pourquoi faire?
| >
| > Implémenter <ctype.h> pour commencer. Ou quelque chose de semblable,
| > avec ses propres classifications.
| >
| > |> c'est hyper dangereux!
| >
| > Utiliser le C++, c'est hyper dangéreux. Je ne vois pas pourquoi quelque
| > chose du genre « table[ ch - CHAR_MIN ] » serait plus dangéreux que
| > d'autre chose.
|
| Quand on soustrait 2 chars, on obtient un char, non ?

Non. On obtient un int.

-- Gaby
Avatar
drkm
Samuel Krempp writes:

le Sunday 22 August 2004 19:35, écrivit :

Utiliser le C++, c'est hyper dangéreux. Je ne vois pas pourquoi quelque
chose du genre « table[ ch - CHAR_MIN ] » serait plus dangéreux que
d'autre chose.


Quand on soustrait 2 chars, on obtient un char, non ?
Alors j'imagine que ce CHAR_MIN est de type int


Pourquoi ?

Il me semble que CHAR_MIN est bien de type « char ». Non ?

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html


Avatar
Philippe Guglielmetti
Michel Michaud wrote in message

iM8Wc.6741$

Dans news:,


Un autre cas, en passant... Comment est-ce que tu écriras une

fonction d'hachage sans l'arithmétique sur des char's ?





je pourrai même choisir la valeur numérique associée à chaque

lettre c et obtenue par MES_LETTRES.find(c) !




houla... j'ai des craintes pour la performance...

je maintiens que considérer char comme un entier est un héritage
malencontrueux du C. Les différences d'implémentation rendent ceci
difficile à maintenir, voire dangereux (James, ton hachage devra être
testé sur différents OS, en Unicode etc).

En C++, il existe static_cast et reinterpret_cast ou le bon vieux
cast a parenthèses du C qui permettrait de considérer char (et bool)
comme un type non-entier, voire une classe, et d'accéder à leur
représentation si besoin. Mais plus de manière transparente, c'est
trop dangereux.

Entre parenthèses, depuis que les int ont 32 bits comme les long (qui
devraient passer à 64, logiquement...), que les shorts en ont 16, et
que wchar_t grignote le bon vieux char à coups de macros cryptiques
pour la "portabilité", il nous faut un vrai "byte" pour la table de
hachage de James.

Les JAVAistes doivent bien se foutre de notre gueule s'ils lisent
ceci.

Philippe Guglielmetti - www.goulu.net


Avatar
Philippe Guglielmetti
drkm wrote in message



Il me semble que CHAR_MIN est bien de type « char ». Non ?




CHAR_MIN est une macro (C...), donc sa valeur dépend du contexte ou
tu l'utilise

#define CHAR_MIN 0

char m=CHAR_MIN; // marche

long* m=CHAR_MIN; // marche aussi

en C++ on devrait utiliser std::numeric_limits<char>::min() qui
renvoie un char, ce qui va faire:

char m=std::numeric_limits<char>::min(); // marche

long* m=std::numeric_limits<char>::min() ; // warning bienvenu

Philippe Guglielmetti - www.goulu.net

Avatar
Samuel Krempp
le Monday 23 August 2004 23:43, écrivit :

Samuel Krempp writes:

le Sunday 22 August 2004 19:35, écrivit :

Utiliser le C++, c'est hyper dangéreux. Je ne vois pas pourquoi quelque
chose du genre « table[ ch - CHAR_MIN ] » serait plus dangéreux que
d'autre chose.


Quand on soustrait 2 chars, on obtient un char, non ?
Alors j'imagine que ce CHAR_MIN est de type int


Pourquoi ?

Il me semble que CHAR_MIN est bien de type « char ». Non ?


Il me semble que si c'est un char, et que char est signed sur la plateforme,
la soustraction de ces 2 char peut déborder, et donner une valeur négative.
ce qui perd l'interêt de faire la soustraction..

--
Sam



1 2 3 4 5