OVH Cloud OVH Cloud

ofstream et fonction write template

78 réponses
Avatar
Aurélien REGAT-BARREL
Bonjour à tous,
Pour mes besoins j'ai défini une fonction write ainsi :

template<typename T>
void write( std::ofstream & Stream, T Value )
{
Stream.write( reinterpret_cast<char*>( &Value ), sizeof T );
}

void main()
{
std::ofstream OutFileStream;
OutFileStream.open( "test" );
int c = 10;
write( OutFileStream, c );
}

Je m'étonne qu'elle n'existe pas déjà dans la STL, ou même carrement en tant
que fonction membre de ofstream. Je pense plutôt que j'ai mal cherché.
Y'a-t-il un équivalent et si non pourquoi ?
Merci.

--
Aurélien REGAT-BARREL

10 réponses

4 5 6 7 8
Avatar
Gabriel Dos Reis
"Michel Michaud" writes:

| Est-ce que C99 a remis (const) char* ? :-)

Non, mais C99 dit que

main(void) { return 0; }

est invalide. -- cela casse _beaucoup_ de codes.

-- Gaby
Avatar
James Kanze
Gabriel Dos Reis writes:

|> writes:

|> [...]

|> | Et évidemment, quelque soit l'intention à Bell Labs, les
|> | programmeurs s'en sont servi comme pointeur générique. Une fois
|> | les conversions implicites entre pointeurs supprimées, en faire
|> | autre chose qu'un void* aurait effectivement cassé pas mal du
|> | code.

|> Pour que l'appel soit « portable », le cast vers char* était
|> nécessaire. Les gens compétents mettaient le cast.

Quand ? Et qu'est-ce que ça veut dire, « portable », à cette époque-là ?

Malloc renvoyait un char*. Personne ne mettait un cast sur sa valeur de
rétour -- au contraire, déjà alors, les gens compétents évitaient le
cast parce qu'il masquait des erreurs potentielles.

--
James Kanze
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
Gabriel Dos Reis
James Kanze writes:

| Gabriel Dos Reis writes:
|
| |> writes:
|
| |> [...]
|
| |> | Et évidemment, quelque soit l'intention à Bell Labs, les
| |> | programmeurs s'en sont servi comme pointeur générique. Une fois
| |> | les conversions implicites entre pointeurs supprimées, en faire
| |> | autre chose qu'un void* aurait effectivement cassé pas mal du
| |> | code.
|
| |> Pour que l'appel soit « portable », le cast vers char* était
| |> nécessaire. Les gens compétents mettaient le cast.
|
| Quand ? Et qu'est-ce que ça veut dire, « portable », à cette époque-là ?
|
| Malloc renvoyait un char*. Personne ne mettait un cast sur sa valeur de

tu veux dire, personne dans les quatre murs qui font ta chambre ? Le
monde est plus grand que ça, James.

| rétour -- au contraire, déjà alors, les gens compétents évitaient le
| cast parce qu'il masquait des erreurs potentielles.

Je ne sais pas qui t'a appris le C, ni où tu l'as appris.
Mais je n'ose pas imaginer que tu étais parmi ces careless programmers.

Dennis M. Ritchie -- l'inventeur du langage C -- dans son bouquin «
The C Programming Language », aussi connu comme le « White Book » © 1978,
est quand à lui très clair sur le cast de char* vers le type pointer idione.

Commençons par la première rencontre avec utilisation de free store.

Chapitre 6, page 133:

Before we leave this example, it is also worth a brief discussion on
a problem related to storage allocators. Clearly it's desirable
that there be only one storage allocator in a program, even though
it allocates different kinds of objects. But if one allocator is to
process requests for, say, pointers to char's and pointers to struct
tnode's, two questions arise. First, how does it meet the
requirement of most real machines that objects of certain type must
satisfy alignment restrictions (for example, integers often must be
located on even addresses)? Second, what declarations can cope with
the fact that alloc necessarily returns different kinds of pointers?

[...]

The question of the type declaration of alloc is a vexing one for
any language that takes its type-checking seriously. In C, the best
procedure is to declare that alloc returns a pointer to char, then
explicitly coerce the pointer into the desired type with a cast.
That is, if p is declared as

char *p;

then

(struct tnode *) p

converts it into a tnode pointer in an expression. Thus talloc is written

(continuation sur p 134)

as

struct tnode *talloc()
{
char *alloc();
return ((struct tnode *) alloc(sizeof(struct tnode)));
}

This is more than is needed for current compilers, but represents
the safest course for the future.


L'inventeur du langage dit que « the best procedure » est de mettre
le cast explicit et que represent the « safest course for the future ».
Non seulement, ile le dit mais il le fait, non seulement dans le
bouquin qu'il a écrit pour enseigner le C, mais aussi dans ses prores
programmes. Je suppose que tu le comptes, lui et ses collègues, comme
« personne » ? Tu as un système cardinal assez singulier.

Regarde page 141, il met encore le cast assez explicitement.
Page 157:

The function calloc is rather like the alloc we have used in
previous chapters.

calloc(n, sizeof(object))

returns a pointer to enough space for n objects of the specified
size, or NULL if the request cannot be satisfied. The storage is
initialized to zero.

The pointer has the proper alignment for the object in question,
but it should be cast into the appropriate type, as in

char* calloc();
int *ip;

ip = (int *) calloc(n, sizeof (int));


Donc, dans la tête de Dennis Ritchie, il n'y avait aucun doute qu'il
fallait caster la valeur de retour.

-- Gaby
Avatar
Michel Michaud
Suite à nos discussions, je me pose une question assez
fondamentale sur void*.

Je suis d'accord sur le principe qu'il y avait certainement un
danger à ne pas forcer une conversion explicite des pointeurs
entre T* (T quelconque) et char*. Ça semble évident si on pense
que les codages pouvaient être différents (et les paramètres non
testés donc non convertis automatiquement). Mais qu'est-ce qui
se passe avec les void* aujourd'hui ? Est-ce comme mettre une
conversion explicite ou comme ne pas vérifier les paramètres
et ne pas faire de conversion ?

Si T* n'est pas identique ni compatible à char* (au niveau codage
interne), que se passe-t-il lorsqu'on passe le T* à une fonction
qui reçoit void* ? Y a-t-il conversion réelle (bits différents) ?
Si oui, vers quoi ? Il faut un format qui sera convertible
universellement en n'importe quoi ensuite. On parlerait de quoi
ici exactement ?

Si le passage de T* à void* ne touche à rien, comment la fonction
peut-elle ensuite convertir vers autre chose (par exemple char*)
et savoir comment faire ? Le codage du pointeur pourrait être
d'une forme ou d'une autre (si l'on accepte l'idée qu'un T1*
peut être différent d'un T2*) et le travail à faire me semble
impossible à deviner...

J'ai travaillé en C et C++ sur bien des architectures, mais je
n'ai pas connu de cas où un char* serait systématiquement
codé différemment d'un autre pointeur sur une donnée. Quelqu'un
peut-il me donner des exemples précis pour que je comprenne un
peu mieux les conversions T* -> char* et T1* -> void* -> T2* ?

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Avatar
James Kanze
Gabriel Dos Reis writes:

|> James Kanze writes:

|> | Gabriel Dos Reis writes:

|> | |> writes:

|> | |> [...]

|> | |> | Et évidemment, quelque soit l'intention à Bell Labs, les
|> | |> | programmeurs s'en sont servi comme pointeur générique. Une
|> | |> | fois les conversions implicites entre pointeurs supprimées,
|> | |> | en faire autre chose qu'un void* aurait effectivement cassé
|> | |> | pas mal du code.

|> | |> Pour que l'appel soit « portable », le cast vers char* était
|> | |> nécessaire. Les gens compétents mettaient le cast.

|> | Quand ? Et qu'est-ce que ça veut dire, « portable », à cette
|> | époque-là ?

|> | Malloc renvoyait un char*. Personne ne mettait un cast sur sa
|> | valeur de

|> tu veux dire, personne dans les quatre murs qui font ta chambre ? Le
|> monde est plus grand que ça, James.

C'est vrai que je n'ai pas vu tout le code qui n'a jamais été écrit.
J'imagine quand même que j'en ai vu plus de cet époque que toi. Y
compris les sources de Unix version 7, où il n'y avait pas de cast sur
des malloc.

|> | rétour -- au contraire, déjà alors, les gens compétents évitaient
|> | le cast parce qu'il masquait des erreurs potentielles.

|> Je ne sais pas qui t'a appris le C, ni où tu l'as appris. Mais je
|> n'ose pas imaginer que tu étais parmi ces careless programmers.

|> Dennis M. Ritchie -- l'inventeur du langage C -- dans son bouquin «
|> The C Programming Language », aussi connu comme le « White Book » ©
|> 1978, est quand à lui très clair sur le cast de char* vers le type
|> pointer idione.

[...]

|> L'inventeur du langage dit que « the best procedure » est de mettre
|> le cast explicit et que represent the « safest course for the future ».
|> Non seulement, ile le dit mais il le fait, non seulement dans le
|> bouquin qu'il a écrit pour enseigner le C, mais aussi dans ses prores
|> programmes. Je suppose que tu le comptes, lui et ses collègues, comme
|> « personne » ? Tu as un système cardinal assez singulier.

Tout ce que je sais, c'est que le cast n'était pas très fréquent dans
les sources de Unix version 7 que j'ai vu. Maintenant, c'est tout à fait
possible que la partie qu'a écrit Kernighan lui-même les utilisait --
dans le noyau (que je présume de Thomson et Richie), il n'y avait pas de
malloc, pour des raisons évidentes, et je ne sais pas qui a écrit quel
utilitaire. (Je suppose que Kernighat a écrit au moins une partie de
AWK, mais je n'avais jamais l'occasion de régarder ses sources. Dans
d'autres utilitaires, en revanche, des malloc sans cast étaient
courants.

[...]
|> Donc, dans la tête de Dennis Ritchie, il n'y avait aucun doute qu'il
|> fallait caster la valeur de retour.

En effet. Mais je n'ai pas eu l'occasion de travailler avec lui à
l'époque. Je sais qu'il y avait une attitude générale parmi une bonne
partie des programmeurs C (dont certains de AT&T) qui le considérer
mauvais style. En fait, l'attitude était surtout prévalente chez des
programmeurs qui avait à faire avec la portabilité. À l'époque, la
déclaration implicite des fonctions était plus ou moin la norme, il n'y
avait pas encore de <stdlib.h>, et il était trop facile à oublier la
declaration de malloc. Du coup, le compilateur supposait qu'elle
renvoyait int.

Or, les compilateurs dont je me servais à l'époque râlait déjà si on
affectait un int à un pointeur. En revanche, ils convertissaient
volentiers char* en n'importe quel autre type de pointeur. Du coup, si
on mettait le cast, on masquait l'erreur d'avoir oublié la déclaration.
Chose auquel on était très sensibilisé, parce que les pointeurs,
c'étaient 32 bits, tandis que les int, seulement 16.

Maintenant, je ne dis pas que c'est peut-être un effet de ce milieu
particuier. C'est même possible que les cast soient ajoutés par les
programmeurs qui ont fait le portage, bien que l'idée ne m'était pas
venue à l'esprit avant. N'empêche qu'ils étaient courants, et c'était un
milieu qui s'y connaissait pas mal -- on ne portait pas Unix sur une
architecture exotique sans une certaine compétence.

--
James Kanze
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
James Kanze
"Michel Michaud" writes:

|> Je suis d'accord sur le principe qu'il y avait certainement un
|> danger à ne pas forcer une conversion explicite des pointeurs entre
|> T* (T quelconque) et char*.

Que la conversion soit implicite ou explicite, le comportement est le
même.

|> Ça semble évident si on pense que les codages pouvaient être
|> différents (et les paramètres non testés donc non convertis
|> automatiquement). Mais qu'est-ce qui se passe avec les void*
|> aujourd'hui ? Est-ce comme mettre une conversion explicite ou comme
|> ne pas vérifier les paramètres et ne pas faire de conversion ?

Dans la mésure que le compilateur connaît les types, la conversion se
fait correctement, qu'elle soit explicite ou implcite. Le seul problème,
c'est le passage des paramètres où le compilateur ne connaît pas le
type. Dans ce cas-là, il suppose qu'on a passé le bon type, et
n'effectue aucune conversion.

|> Si T* n'est pas identique ni compatible à char* (au niveau codage
|> interne), que se passe-t-il lorsqu'on passe le T* à une fonction qui
|> reçoit void* ?

S'il y a un prototype en vue, il y a une conversion implicite.

|> Y a-t-il conversion réelle (bits différents) ?

S'il y a un prototype.

|> Si oui, vers quoi ?

Pour des raisons historiques, la norme exige que les représentations des
void* et de char* soient identiques. Selon la norme, il y a conversion
en void* ; dans la pratique, une conversion en void* et une conversion
en char* font faire exactement la même chose.

|> Il faut un format qui sera convertible universellement en n'importe
|> quoi ensuite.

C'est bien la définition de void*.

|> On parlerait de quoi ici exactement ?

|> Si le passage de T* à void* ne touche à rien, comment la fonction
|> peut-elle ensuite convertir vers autre chose (par exemple char*) et
|> savoir comment faire ?

Il faut évidemment qu'un void* ait une représentation définie non
ambigüe. Je crois que la norme dit aussi que cette représentation doit
être identique à celle des char*. Dans la pratique, c'est toujours le
cas, en tout cas.

|> Le codage du pointeur pourrait être d'une forme ou d'une autre (si
|> l'on accepte l'idée qu'un T1* peut être différent d'un T2*) et le
|> travail à faire me semble impossible à deviner...

|> J'ai travaillé en C et C++ sur bien des architectures, mais je n'ai
|> pas connu de cas où un char* serait systématiquement codé
|> différemment d'un autre pointeur sur une donnée.

Moi si. En fait, dans un des compilateurs portables sur lequel j'ai
travaillé, on distinguait quatre types de pointeurs : vers les
fonctions, vers les étiquettes (non accessible directement en C, mais
utilisé, par exemple, dans l'implémentation d'un switch), vers les
données autres que char, et vers les char.

|> Quelqu'un peut-il me donner des exemples précis pour que je
|> comprenne un peu mieux les conversions T* -> char* et T1* -> void*
|> -> T2* ?

C'est assez simple, en fait. Au niveau le plus bas, un void* est un
char*. Et un char* est capable d'adresser n'importe quel octet. Quand on
convertit un T* en char*, on met les bits selecteurs d'octet du char* à
zéro. Quand on convertit un char* en T*, on ignore les bits selecteurs
d'octet. (Au moins, c'est comme ça que ça passait dans le seul cas que
je connais.)

--
James Kanze
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
Gabriel Dos Reis
James Kanze writes:

| Gabriel Dos Reis writes:
|
| |> James Kanze writes:
|
| |> | Gabriel Dos Reis writes:
|
| |> | |> writes:
|
| |> | |> [...]
|
| |> | |> | Et évidemment, quelque soit l'intention à Bell Labs, les
| |> | |> | programmeurs s'en sont servi comme pointeur générique. Une
| |> | |> | fois les conversions implicites entre pointeurs supprimées,
| |> | |> | en faire autre chose qu'un void* aurait effectivement cassé
| |> | |> | pas mal du code.
|
| |> | |> Pour que l'appel soit « portable », le cast vers char* était
| |> | |> nécessaire. Les gens compétents mettaient le cast.
|
| |> | Quand ? Et qu'est-ce que ça veut dire, « portable », à cette
| |> | époque-là ?
|
| |> | Malloc renvoyait un char*. Personne ne mettait un cast sur sa
| |> | valeur de
|
| |> tu veux dire, personne dans les quatre murs qui font ta chambre ? Le
| |> monde est plus grand que ça, James.
|
| C'est vrai que je n'ai pas vu tout le code qui n'a jamais été écrit.
| J'imagine quand même que j'en ai vu plus de cet époque que toi. Y

Oh mais je n'en doute pas une seule seconde. N'empêche que les
arguments d'anciens combattants sont spécieux ; et j'ai appris par le
temps a m'en méfier surtout lorsqu'ils viennent de toi. N'y vois
aucune attaque personnelle.

Tu as affirmé que personne ne mettait un cast sur la valeur de cast.
Or je viens juste de montrer qu'au moins les auteurs de The C
Programming Language (parmi lesquels, l'inventeur du langage) le font
et le recommandent. Non seulement, ils l'ont écrit dans la première
version de K&R, mais ils le réitèrent dans sa seconde version (oµ
void* et sa conversion implicite vers T* existent). Ces gentlemen se
souciaient aussi de la portabilité et le font savoir à qui veut
l'entendre -- avec preuves à l'appui.

Je n'irai pas jusqu'à dire que tu viens de perdre toute crédibilité
(c'est un risque avec les arguments d'anciens combattants) mais au
moins, il devient apparent qu'il y a peu de vérité/réalité dans tes
souvenances ou arguments d'anciens combattants. Et s'il te plaît, ne
vient pas me faire le coup de l'hyperbole -- les blagues les plus
courtes sont les meilleures.

[...]

| Tout ce que je sais, c'est que le cast n'était pas très fréquent dans
| les sources de Unix version 7 que j'ai vu.

Il y a une différence notable entre personne ne mettait le cast et le
cast n'était pas fréquent -- non, ce n'est pas de l'hyperbole.
Tu as aussi par le passé affirmé que tu as appris le C du bouquin de
Kernighan et Ritchie ; alors tu aurais dû savoir que ces gentlemen
mettaient le cast.

| Maintenant, c'est tout à fait
| possible que la partie qu'a écrit Kernighan lui-même les utilisait --

Et Dennis Ritchie aussi, et nombreux de ses collègues aussi.

| dans le noyau (que je présume de Thomson et Richie), il n'y avait pas de
| malloc, pour des raisons évidentes, et je ne sais pas qui a écrit quel

Mais pour ce qui nous concerne, ce n'était pas très différent de
alloc() ou calloc().

[...]

| |> Donc, dans la tête de Dennis Ritchie, il n'y avait aucun doute qu'il
| |> fallait caster la valeur de retour.
|
| En effet. Mais je n'ai pas eu l'occasion de travailler avec lui à
| l'époque.

Mais personne ne t'en veut pour ça, James. Il est clair qu'il ne pouvait
pas travailler avec tous les programmeurs C en même temps.

| Je sais qu'il y avait une attitude générale parmi une bonne
| partie des programmeurs C (dont certains de AT&T) qui le considérer
| mauvais style. En fait, l'attitude était surtout prévalente chez des
| programmeurs qui avait à faire avec la portabilité. À l'époque, la

Mais Dennis Ritchie et ses collègues payent une attention particulière
à la portabilité.

[ Dans GCC, par exemple, nous payons une attention particulière
aussi à la portabilité ; en particulier, nous programmions en C
classique (grosso modo C K&R) jusqu'à une époque très récente et nous
mettions le cast explicitement. Et nous allons continuer à le faire. ]

Je crois qu'à ce stade, tu jettes encore plus de brouillard avec des
explications abracadabrantesques.

| déclaration implicite des fonctions était plus ou moin la norme, il n'y
| avait pas encore de <stdlib.h>, et il était trop facile à oublier la
| declaration de malloc. Du coup, le compilateur supposait qu'elle
| renvoyait int.
|
| Or, les compilateurs dont je me servais à l'époque râlait déjà si on
| affectait un int à un pointeur. En revanche, ils convertissaient
| volentiers char* en n'importe quel autre type de pointeur. Du coup, si

Donc, tu penses que tu le monde se résume à tes quatre murs et que ce
que tu n'y fais pas, personne ne fait ?

-- Gaby
Avatar
kanze
Gabriel Dos Reis wrote in message
news:...
James Kanze writes:

| Gabriel Dos Reis writes:

| |> James Kanze writes:

| |> | Gabriel Dos Reis writes:

| |> | |> writes:

| |> | |> [...]

| |> | |> | Et évidemment, quelque soit l'intention à Bell Labs, les
| |> | |> | programmeurs s'en sont servi comme pointeur
| |> | |> | générique. Une fois les conversions implicites entre
| |> | |> | pointeurs supprimées, en faire autre chose qu'un void*
| |> | |> | aurait effectivement cassé pas mal du code.

| |> | |> Pour que l'appel soit « portable », le cast vers char*
| |> | |> était nécessaire. Les gens compétents mettaient le cast.

| |> | Quand ? Et qu'est-ce que ça veut dire, « portable », à cette
| |> | époque-là ?

| |> | Malloc renvoyait un char*. Personne ne mettait un cast sur sa
| |> | valeur de

| |> tu veux dire, personne dans les quatre murs qui font ta chambre
| |> ? Le monde est plus grand que ça, James.

| C'est vrai que je n'ai pas vu tout le code qui n'a jamais été écrit.
| J'imagine quand même que j'en ai vu plus de cet époque que toi. Y

Oh mais je n'en doute pas une seule seconde. N'empêche que les
arguments d'anciens combattants sont spécieux ; et j'ai appris par le
temps a m'en méfier surtout lorsqu'ils viennent de toi. N'y vois
aucune attaque personnelle.


Il y a effectivement une différence de taille. Tu lis dans les bouquins,
et tu racontes comment ça aurait dû être. Moi, j'y étais, et je raconte
comment c'était.

Dans ce cas-précis, je ne nie pas que le cast était théoriquement
préférable. Seulement, j'y étais, je sais ce qu'on faisait, et je sais
pourquoi. Il y avait des raisons fort pratiques pour préférer ne pas
utiliser le cast.

Tu as affirmé que personne ne mettait un cast sur la valeur de cast.


Il me semblait évident que « personne », c'est du rhétorique. Il me
semblait évident que je ne savais pas ce que faisait tout le monde, et
qu'il se peut qu'il y avait des ilôts où le cast était de rigueur. Mais
ces ilôts faisaient bien exception, parce que dans la practique, le cast
posait des problèmes de maintainabilité quand il s'agissait du code
portable.

Or je viens juste de montrer qu'au moins les auteurs de The C
Programming Language (parmi lesquels, l'inventeur du langage) le font
et le recommandent.


Tu m'as montré que c'était leur intention que le cast soit nécessaire.
Chose qui, tout compte fait, me semble raisonable. Tu ne m'as pas montré
qu'ils faisaient ce qu'ils disaient, mais bon, je n'ai pas trop de
raison à le douter.

Moi, en revanche, j'ai bien vu du code par leurs collègues mêmes sans le
cast. C'est possible le code avait été modifié par la suite, pour
résoudre des problèmes de portabilité. Mais c'est aussi possible qu'il y
avait un écart entre ce que K&R disent dans leur bouquin, et ce qui se
faisaient, y compris dans les bureaux où ils travaillaient.

Non seulement, ils l'ont écrit dans la première version de K&R, mais
ils le réitèrent dans sa seconde version (oµ void* et sa conversion
implicite vers T* existent). Ces gentlemen se souciaient aussi de la
portabilité et le font savoir à qui veut l'entendre -- avec preuves à
l'appui.


Ces gentlemen ne représentent qu'un faible pourcentage des
programmateurs en C. Même à l'époque où j'ai commencé le C.

Je t'ai expliqué pourquoi on évitait le cast. C'est une raison pûrement
pragmatique -- ce n'est pas qu'on le trouve élégant ou beau. Mais dans
la mésure où les declarations implicites des fonctions étaient la norme,
ça évitait un certain nombre de problèmes.

Je n'irai pas jusqu'à dire que tu viens de perdre toute crédibilité
(c'est un risque avec les arguments d'anciens combattants) mais au
moins, il devient apparent qu'il y a peu de vérité/réalité dans tes
souvenances ou arguments d'anciens combattants. Et s'il te plaît, ne
vient pas me faire le coup de l'hyperbole -- les blagues les plus
courtes sont les meilleures.


Reveille-toi. Le monde réel n'est pas fait uniquement des tes théories
livresques.

[...]

| Tout ce que je sais, c'est que le cast n'était pas très fréquent
| dans les sources de Unix version 7 que j'ai vu.

Il y a une différence notable entre personne ne mettait le cast et le
cast n'était pas fréquent -- non, ce n'est pas de l'hyperbole.


C'est du rhétorique. C'est une façon de parler. C'est tout ce que tu
veux. Je sais pertinement bien que je ne sais pas ce que faisait 100%
des programmeurs C à un époque donné. Soyons réaliste.

Je ne sais pas si tu te rends compte, mais ce que j'écris ici, ce n'est
pas destiné à un compilateur, mais à des êtres humains, qui comprenent
les nuances du langage humain. J'ai réelement du mal à imaginer
quelqu'un qui interprête ma « personne » comme signifiant que je nie
dans l'absolu l'existance possible d'une telle utilisation. C'est une
façon à dire qu'une certaine utilisation était la norme.

Tu as aussi par le passé affirmé que tu as appris le C du bouquin de
Kernighan et Ritchie ; alors tu aurais dû savoir que ces gentlemen
mettaient le cast.


J'ai appris le C par le K&R, oui. Pour commencer. Évidemment, par la
suite, j'en ai perfectionné mes connaissances par la pratique, et la
lecture du code des autres.

| Maintenant, c'est tout à fait possible que la partie qu'a écrit
| Kernighan lui-même les utilisait --

Et Dennis Ritchie aussi, et nombreux de ses collègues aussi.


Mais pas ceux qui ont écrit les parties du Unix où j'ai vue l'absences
des casts.

| dans le noyau (que je présume de Thomson et Richie), il n'y avait
| pas de malloc, pour des raisons évidentes, et je ne sais pas qui a
| écrit quel

Mais pour ce qui nous concerne, ce n'était pas très différent de
alloc() ou calloc().


Dans le noyau de la version 7, les tables systèmes étaient allouées
statiquement -- il n'y avait pas autant d'allocation dynamique que ça.
(Il doit bien y avoir eu par endroits, mais j'avoue ne pas rappeler d'en
avoir vu. La seule choses que j'ai vu qui était geré à peu près
dynamiquement, c'était le pool des buffers. Mais là, la question ne se
posait pas, parce que les buffers étaient bien des char* aussi lors de
l'utilisation.)

[...]

| Je sais qu'il y avait une attitude générale parmi une bonne partie
| des programmeurs C (dont certains de AT&T) qui le considérer mauvais
| style. En fait, l'attitude était surtout prévalente chez des
| programmeurs qui avait à faire avec la portabilité. À l'époque, la

Mais Dennis Ritchie et ses collègues payent une attention particulière
à la portabilité.


Tout à fait. Et je te repète que j'ai bien vu des malloc sans cast dans
du code sorti des Bell Labs.

[...]

| déclaration implicite des fonctions était plus ou moin la norme, il
| n'y avait pas encore de <stdlib.h>, et il était trop facile à
| oublier la declaration de malloc. Du coup, le compilateur supposait
| qu'elle renvoyait int.

| Or, les compilateurs dont je me servais à l'époque râlait déjà si on
| affectait un int à un pointeur. En revanche, ils convertissaient
| volentiers char* en n'importe quel autre type de pointeur. Du coup,
| si

Donc, tu penses que tu le monde se résume à tes quatre murs et que ce
que tu n'y fais pas, personne ne fait ?


À l'encontre de toi, je me suis pas contenté de lire un livre, et de
croire que tout le monde faisait exactement ce qui y était conseillé. Je
ne suis pas si borné que certains ; je sors dans le monde réel où les
gens développent du code pratique. Et il s'avère que là, parfois, les
belles théories ne marchent pas comme prévues.

--
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
Loïc Joly
Gabriel Dos Reis wrote:

James Kanze writes:

| Malloc renvoyait un char*. Personne ne mettait un cast sur sa valeur de

tu veux dire, personne dans les quatre murs qui font ta chambre ? Le
monde est plus grand que ça, James.

| rétour -- au contraire, déjà alors, les gens compétents évitaient le
| cast parce qu'il masquait des erreurs potentielles.

Je ne sais pas qui t'a appris le C, ni où tu l'as appris.
Mais je n'ose pas imaginer que tu étais parmi ces careless programmers.

Dennis M. Ritchie -- l'inventeur du langage C -- dans son bouquin «
The C Programming Language », aussi connu comme le « White Book » © 1978,
est quand à lui très clair sur le cast de char* vers le type pointer idione.


Ce nos jours, quand on regarde par exemple sur f.c.l.c, les gens
déconseillent (assez unanimement) vivement le cast en sortie du malloc
(ce qui pose des problèmes puisque le code en question ne peut pas alors
être compilé par un compilateur C++). Quelqu'un a-t-il une idée de quand
(et pourquoi) la ligne officielle du parti de ne pas mettre de cast est
apparue ?

--
Loïc

Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote in message
| news:...
| > James Kanze writes:
|
| > | Gabriel Dos Reis writes:
|
| > | |> James Kanze writes:
|
| > | |> | Gabriel Dos Reis writes:
|
| > | |> | |> writes:
|
| > | |> | |> [...]
|
| > | |> | |> | Et évidemment, quelque soit l'intention à Bell Labs, les
| > | |> | |> | programmeurs s'en sont servi comme pointeur
| > | |> | |> | générique. Une fois les conversions implicites entre
| > | |> | |> | pointeurs supprimées, en faire autre chose qu'un void*
| > | |> | |> | aurait effectivement cassé pas mal du code.
|
| > | |> | |> Pour que l'appel soit « portable », le cast vers char*
| > | |> | |> était nécessaire. Les gens compétents mettaient le cast.
|
| > | |> | Quand ? Et qu'est-ce que ça veut dire, « portable », à cette
| > | |> | époque-là ?
|
| > | |> | Malloc renvoyait un char*. Personne ne mettait un cast sur sa
| > | |> | valeur de
|
| > | |> tu veux dire, personne dans les quatre murs qui font ta chambre
| > | |> ? Le monde est plus grand que ça, James.
|
| > | C'est vrai que je n'ai pas vu tout le code qui n'a jamais été écrit.
| > | J'imagine quand même que j'en ai vu plus de cet époque que toi. Y
|
| > Oh mais je n'en doute pas une seule seconde. N'empêche que les
| > arguments d'anciens combattants sont spécieux ; et j'ai appris par le
| > temps a m'en méfier surtout lorsqu'ils viennent de toi. N'y vois
| > aucune attaque personnelle.
|
| Il y a effectivement une différence de taille. Tu lis dans les bouquins,
| et tu racontes comment ça aurait dû être.

En réalité, je sais de source de première main ce qui se partiquait
dans l'entourage de Ricthie, mais au lieu de venir dire "le mec au
dessus de moi dit le contraire", j'ai pensé plutôt donner une source
que tout le monde pouvait vérifier, sur l'opinion et la pratique de
Ritchie.

| Moi, j'y étais, et je raconte comment c'était.

Et si j'étais venu te dire que le gars à l'étage aussi de moi avait son
bureau juste à côté de celui de Ritchie et y était lui aussi, dans ce
sesn qu'il travaillait, lui, avec Ritchie et Kernighan? Cela aurait
été juste un autre argument d'ancien combattant. Mais visiblement tu
préfères les arguments d'anciens combattants, alors je te le sers.

| Dans ce cas-précis, je ne nie pas que le cast était théoriquement
| préférable. Seulement, j'y étais, je sais ce qu'on faisait, et je sais

Il y a ce que toi, James, faisais, et ce que les autres faisaient.
Ce n'est pas parce que tu ne faisais pas quelque chose que cela veut
dire que personne d'autre ne le fait. Non, James, tu ne faisais pas de
la rhétorique : tu mentais simplement.

| pourquoi. Il y avait des raisons fort pratiques pour préférer ne pas
| utiliser le cast.
|
| > Tu as affirmé que personne ne mettait un cast sur la valeur de cast.
|
| Il me semblait évident que « personne », c'est du rhétorique. Il me

Oui, le mensonge effronté était évident. Mais encore fallait-il que tu
le reconnaisses.

[...]

| Moi, en revanche, j'ai bien vu du code par leurs collègues mêmes sans le
| cast.

Et moi, j'en en face de moi

| C'est possible le code avait été modifié par la suite, pour
| résoudre des problèmes de portabilité. Mais c'est aussi possible qu'il y
| avait un écart entre ce que K&R disent dans leur bouquin, et ce qui se
| faisaient, y compris dans les bureaux où ils travaillaient.

Bouhahahahahaha.

| > Non seulement, ils l'ont écrit dans la première version de K&R, mais
| > ils le réitèrent dans sa seconde version (oµ void* et sa conversion
| > implicite vers T* existent). Ces gentlemen se souciaient aussi de la
| > portabilité et le font savoir à qui veut l'entendre -- avec preuves à
| > l'appui.
|
| Ces gentlemen ne représentent qu'un faible pourcentage des
| programmateurs en C. Même à l'époque où j'ai commencé le C.

C'est pour cela qu'ils sont « personne ».

| Je t'ai expliqué pourquoi on évitait le cast.

Tu as expliqué pourquoi *tu* évitais le cast. Ritchie et Kernighan eux
ont expliqué pourquoi ils mettaient

| C'est une raison pûrement
| pragmatique -- ce n'est pas qu'on le trouve élégant ou beau. Mais dans
| la mésure où les declarations implicites des fonctions étaient la norme,
| ça évitait un certain nombre de problèmes.

J'ai écris « careless », et ce n'est pas pour rien.

| > Je n'irai pas jusqu'à dire que tu viens de perdre toute crédibilité
| > (c'est un risque avec les arguments d'anciens combattants) mais au
| > moins, il devient apparent qu'il y a peu de vérité/réalité dans tes
| > souvenances ou arguments d'anciens combattants. Et s'il te plaît, ne
| > vient pas me faire le coup de l'hyperbole -- les blagues les plus
| > courtes sont les meilleures.
|
| Reveille-toi. Le monde réel n'est pas fait uniquement des tes théories
| livresques.

Oh mais j'étais bien réveillé, c'est pour cela que j'ai bien préféré
aller kidnapper l'exemple de K&R1 du mec au dessus de moi au lieu de
m'arrêter à son "Mais bien sûr qu'ils [Ritchie, Kernighan et les
autres] mettaient le cast. D'ailleurs, si tu regardes ceci et cela tu
verras bien les casts" -- que je croyais tout à fait puisqu'il m'avait
déjà montré d'autres exemples durant d'autres discussions.

Et ce que j'ai montré n'est pas une connaissance livresque.

| > [...]
|
| > | Tout ce que je sais, c'est que le cast n'était pas très fréquent
| > | dans les sources de Unix version 7 que j'ai vu.
|
| > Il y a une différence notable entre personne ne mettait le cast et le
| > cast n'était pas fréquent -- non, ce n'est pas de l'hyperbole.
|
| C'est du rhétorique.

Non, c'est du mensonge effronté.

| C'est une façon de parler. C'est tout ce que tu
| veux. Je sais pertinement bien que je ne sais pas ce que faisait 100%
| des programmeurs C à un époque donné. Soyons réaliste.

Bouhahahahahahaha.

| Je ne sais pas si tu te rends compte, mais ce que j'écris ici, ce n'est

Je ne sais pas si tu te rends compte mais, ton utilisation de
« personne » était faite dans un contexte bien précis.

Tu as simplemnt menti et cherché à donner des explications fumeuses.
Mais, je ne t'en veux pas d'en arriver là à vouloir de te la péter
avec tes histoires d'anciens combattants. Seulement l'honnêteté
intellectuelle aurait voulu que tu t'en arrêtes là au lieu d'insinuer
que ces gentlemen faisaient une belle théorie dans leur bouquin et
pratiquaient autre chose à côté.
M'enfin ils ont entendu pire.

[...]

| > Mais pour ce qui nous concerne, ce n'était pas très différent de
| > alloc() ou calloc().
|
| Dans le noyau de la version 7, les tables systèmes étaient allouées
| statiquement --

Mais que alloc() ou calloc() allouent réellement dynamiquement
ou utilisent de la mémoire pré-allouée statiquement, ne change
absolument fondamentalement rien à la question du cast.

[...]

| > | déclaration implicite des fonctions était plus ou moin la norme, il
| > | n'y avait pas encore de <stdlib.h>, et il était trop facile à
| > | oublier la declaration de malloc. Du coup, le compilateur supposait
| > | qu'elle renvoyait int.
|
| > | Or, les compilateurs dont je me servais à l'époque râlait déjà si on
| > | affectait un int à un pointeur. En revanche, ils convertissaient
| > | volentiers char* en n'importe quel autre type de pointeur. Du coup,
| > | si
|
| > Donc, tu penses que tu le monde se résume à tes quatre murs et que ce
| > que tu n'y fais pas, personne ne fait ?
|
| À l'encontre de toi, je me suis pas contenté de lire un livre, et de
| croire que tout le monde faisait exactement ce qui y était conseillé. Je

Mais je ne me suis pas contenté de croire ce qui était dans le livre
et d'ailleurs, je n'ai pas affirmé que tout le monde faisait ce qui
était conseillé -- je prends pour principe qu'il y a toujours des
énergumènes qui diront que personne ne fait quelque chose en dépis
même de la réalité. La seule exitence même de ton mensonge effronté
était une preuve que d'autres personnes faisaient probablement autre
chose.

| ne suis pas si borné que certains ;

Ah mais c'est ce que tu affirmes ; cela reste à prouver. C'est tout le
problème avec tes affirmations.

-- Gaby
4 5 6 7 8