Jean-Marc Bourguet a écrit :Wykaaa writes:Jean-Marc Bourguet a écrit :Wykaaa writes:Les tableaux C sont déjà une source de confusion assez grande comme
cela; faire croire que le nom d'un tableau a un type pointeur ne fait
qu'augmenter la confusion -- en particulier en C++.
Désolé, mais "un type pointeur", ça ne veut rien dire puisque les pointeurs
sont... typés.
Bizarre, l'expression se trouve dans les normes C90, C++98, C99 et le
dernier brouillon disponible de C++0X avec le sens que je lui donne ici.
La norme ne devrait pas dire "type pointeur", elle devrait dire "de nature
pointeur".
De toute façon, il y a belle lurette que je ne fais pas confiance à la
norme pour le vocabulaire car il semble qu'il n'a pas été porté une
attention suffisante sur ce point tout au long de la norme...
Je voulais dire que le nom de tableau est manipulé comme un pointeur
(d'ailleurs du type des éléments).
Pas dans tous les contextes:
void f(int (&t)[10]);
template <typename T>
void g(T&);
int tab[10];
Dans aucune des expressions sizeof tab, &tab, typeid(tab), f(tab), g(tab)
tab n'est converti en un pointeur vers son premier élément.
Certes mais cependant tout le monde parle de l'équivalence pointeur/tableau
à propos de C. Donc c'est un peu jouer sur les mots de ne pas reconnaître
qu'il y a souvent confusion pour les utilisateurs.
S'il n'y avait pas cette "équivalence" pointeur/tableau, il n'y aurait pas
besoin des [] pour indiquer à delete que le pointeur pointe sur un tableau
alloué dynamiquement afin d'appeler les destructeurs pour chaque instance.
J'ai du mal à comprendre ce que tu veux dire. Dans
int* t = new int[10];
delete[] t;
la conversion implicite d'un tableau en un pointeur n'intervient pas.
Certes mais il faut mettre les crochets car C, donc C++, n'est pas capable
de distinguer, de lui-même, entre un pointeur sur variable scalaire et un
pointeur sur tableau.
Il faut "l'aider", ce qui est anormal. Si le langage
était "bien fichu" il n'y aurait pas besoin de cette syntaxe pour le moins
bizarre. Il n'y a qu'à voir le nombre de questions sur ce sujet dans les
différents fora Internet.
Onla virerait et on permettrait d'appliquer [] sur les tableaux qu'il y a peu
de choses qui changerait à part les appels de fonctions.
Oui mais les appels de fonction, c'est quand même important non ?
Par ailleurs, l'objectif de simplifier la conversion du code B existant a
été source d'autres mauvais choix comme la priorité des opérateurs, en
particulier pour les opérateurs sur bits (&) par rapport à = ou ==.
Jean-Marc Bourguet a écrit :
Wykaaa <wykaaa@yahoo.fr> writes:
Jean-Marc Bourguet a écrit :
Wykaaa <wykaaa@yahoo.fr> writes:
Les tableaux C sont déjà une source de confusion assez grande comme
cela; faire croire que le nom d'un tableau a un type pointeur ne fait
qu'augmenter la confusion -- en particulier en C++.
Désolé, mais "un type pointeur", ça ne veut rien dire puisque les pointeurs
sont... typés.
Bizarre, l'expression se trouve dans les normes C90, C++98, C99 et le
dernier brouillon disponible de C++0X avec le sens que je lui donne ici.
La norme ne devrait pas dire "type pointeur", elle devrait dire "de nature
pointeur".
De toute façon, il y a belle lurette que je ne fais pas confiance à la
norme pour le vocabulaire car il semble qu'il n'a pas été porté une
attention suffisante sur ce point tout au long de la norme...
Je voulais dire que le nom de tableau est manipulé comme un pointeur
(d'ailleurs du type des éléments).
Pas dans tous les contextes:
void f(int (&t)[10]);
template <typename T>
void g(T&);
int tab[10];
Dans aucune des expressions sizeof tab, &tab, typeid(tab), f(tab), g(tab)
tab n'est converti en un pointeur vers son premier élément.
Certes mais cependant tout le monde parle de l'équivalence pointeur/tableau
à propos de C. Donc c'est un peu jouer sur les mots de ne pas reconnaître
qu'il y a souvent confusion pour les utilisateurs.
S'il n'y avait pas cette "équivalence" pointeur/tableau, il n'y aurait pas
besoin des [] pour indiquer à delete que le pointeur pointe sur un tableau
alloué dynamiquement afin d'appeler les destructeurs pour chaque instance.
J'ai du mal à comprendre ce que tu veux dire. Dans
int* t = new int[10];
delete[] t;
la conversion implicite d'un tableau en un pointeur n'intervient pas.
Certes mais il faut mettre les crochets car C, donc C++, n'est pas capable
de distinguer, de lui-même, entre un pointeur sur variable scalaire et un
pointeur sur tableau.
Il faut "l'aider", ce qui est anormal. Si le langage
était "bien fichu" il n'y aurait pas besoin de cette syntaxe pour le moins
bizarre. Il n'y a qu'à voir le nombre de questions sur ce sujet dans les
différents fora Internet.
On
la virerait et on permettrait d'appliquer [] sur les tableaux qu'il y a peu
de choses qui changerait à part les appels de fonctions.
Oui mais les appels de fonction, c'est quand même important non ?
Par ailleurs, l'objectif de simplifier la conversion du code B existant a
été source d'autres mauvais choix comme la priorité des opérateurs, en
particulier pour les opérateurs sur bits (&) par rapport à = ou ==.
Jean-Marc Bourguet a écrit :Wykaaa writes:Jean-Marc Bourguet a écrit :Wykaaa writes:Les tableaux C sont déjà une source de confusion assez grande comme
cela; faire croire que le nom d'un tableau a un type pointeur ne fait
qu'augmenter la confusion -- en particulier en C++.
Désolé, mais "un type pointeur", ça ne veut rien dire puisque les pointeurs
sont... typés.
Bizarre, l'expression se trouve dans les normes C90, C++98, C99 et le
dernier brouillon disponible de C++0X avec le sens que je lui donne ici.
La norme ne devrait pas dire "type pointeur", elle devrait dire "de nature
pointeur".
De toute façon, il y a belle lurette que je ne fais pas confiance à la
norme pour le vocabulaire car il semble qu'il n'a pas été porté une
attention suffisante sur ce point tout au long de la norme...
Je voulais dire que le nom de tableau est manipulé comme un pointeur
(d'ailleurs du type des éléments).
Pas dans tous les contextes:
void f(int (&t)[10]);
template <typename T>
void g(T&);
int tab[10];
Dans aucune des expressions sizeof tab, &tab, typeid(tab), f(tab), g(tab)
tab n'est converti en un pointeur vers son premier élément.
Certes mais cependant tout le monde parle de l'équivalence pointeur/tableau
à propos de C. Donc c'est un peu jouer sur les mots de ne pas reconnaître
qu'il y a souvent confusion pour les utilisateurs.
S'il n'y avait pas cette "équivalence" pointeur/tableau, il n'y aurait pas
besoin des [] pour indiquer à delete que le pointeur pointe sur un tableau
alloué dynamiquement afin d'appeler les destructeurs pour chaque instance.
J'ai du mal à comprendre ce que tu veux dire. Dans
int* t = new int[10];
delete[] t;
la conversion implicite d'un tableau en un pointeur n'intervient pas.
Certes mais il faut mettre les crochets car C, donc C++, n'est pas capable
de distinguer, de lui-même, entre un pointeur sur variable scalaire et un
pointeur sur tableau.
Il faut "l'aider", ce qui est anormal. Si le langage
était "bien fichu" il n'y aurait pas besoin de cette syntaxe pour le moins
bizarre. Il n'y a qu'à voir le nombre de questions sur ce sujet dans les
différents fora Internet.
Onla virerait et on permettrait d'appliquer [] sur les tableaux qu'il y a peu
de choses qui changerait à part les appels de fonctions.
Oui mais les appels de fonction, c'est quand même important non ?
Par ailleurs, l'objectif de simplifier la conversion du code B existant a
été source d'autres mauvais choix comme la priorité des opérateurs, en
particulier pour les opérateurs sur bits (&) par rapport à = ou ==.
Jean-Marc Bourguet a écrit :
> Wykaaa writes:
>> Jean-Marc Bourguet a écrit :
>>> Wykaaa writes:
>>>> Jean-Marc Bourguet a écrit :
>>>>> Wykaaa writes:
>>>>> Les tableaux C sont déjà une source de confusion assez grand e comme
>>>>> cela; faire croire que le nom d'un tableau a un type pointeur ne fa it
>>>>> qu'augmenter la confusion -- en particulier en C++.
>>>> Désolé, mais "un type pointeur", ça ne veut rien dire
>>>> puisque les pointeurs sont... typés.
>>> Bizarre, l'expression se trouve dans les normes C90,
>>> C++98, C99 et le dernier brouillon disponible de C++0X
>>> avec le sens que je lui donne ici.
>> La norme ne devrait pas dire "type pointeur", elle devrait
>> dire "de nature pointeur".
> Le mot est en italique dans la partie que j'ai regardé: la
> norme donne une définition du terme. Au même endroit
> qu'elle défini les autres types dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer
type" était en italique dns la référence que tu m'as fournie
plus loin.
>> De toute façon, il y a belle lurette que je ne fais pas
>> confiance à la norme pour le vocabulaire car il semble
>> qu'il n'a pas été porté une attention suffisante sur ce
>> point tout au long de la norme...
> C'est le moment de donner tes commentaires.
>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui
figurent dans le texte ne sont définis nulle part.
>>>> S'il n'y avait pas cette "équivalence" pointeur/tableau,
>>>> il n'y aurait pas besoin des [] pour indiquer à delete
>>>> que le pointeur pointe sur un tableau alloué
>>>> dynamiquement afin d'appeler les destructeurs pour chaque
>>>> instance.
>>> J'ai du mal à comprendre ce que tu veux dire. Dans
>>> int* t = new int[10];
>>> delete[] t;
>>> la conversion implicite d'un tableau en un pointeur
>>> n'intervient pas.
>> Certes mais il faut mettre les crochets car C, donc C++,
>> n'est pas capable de distinguer, de lui-même, entre un
>> pointeur sur variable scalaire et un pointeur sur tableau.
> Ne referais-tu pas la même erreur de nomenclature que celle
> qui a lancé cette discussion?
> int* x;
> int (*x)[10];
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
>> Il faut "l'aider", ce qui est anormal. Si le langage était
>> "bien fichu" il n'y aurait pas besoin de cette syntaxe pour
>> le moins bizarre. Il n'y a qu'à voir le nombre de questions
>> sur ce sujet dans les différents fora Internet.
>>>On la virerait et on permettrait d'appliquer [] sur les
>>>tableaux qu'il y a peu de choses qui changerait à part les
>>>appels de fonctions.
>> Oui mais les appels de fonction, c'est quand même important
>> non ?
> On aurait fait pour les tableaux ce qui a été fait pour les
> structures -- permettre le passage par valeur, être obligé
> d'utiliser & pour passer un pointeur -- il y aurait beaucoup
> de confusion en moins sans changer fondamentalement le
> rapport entre tableaux et pointeurs (dont la substantifique
> moelle est pour moi l'arithmétique sur les pointeurs).
Ben voilà. Ca serait déjà beaucoup mieux.
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type array of N T or array of
unknown bound of T can be converted to an rvalue of type
pointer to T. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
>> Par ailleurs, l'objectif de simplifier la conversion du
>> code B existant a été source d'autres mauvais choix comme
>> la priorité des opérateurs, en particulier pour les
>> opérateurs sur bits (&) par rapport à = ou ==.
> Ah ce qu'on garde par soucis de faciliter la transition même
> si ce n'est pas idéal et qu'il faudra vivre avec -- on le
> sait bien souvent au moment même ou on prend la décision,
> mais on a l'impression, souvent fondée, que c'est nécessaire
> pour vivre longtemps... et ce n'est pas propre au C (envers
> B et BCPL) et au C++ (envers le C) ni même aux langages ou à
> l'informatique.
En C, lors de la normalisation, on s'est bien débarrassé du
trait de langage très ennuyeux qui consistait à pouvoir faire
un branchement au milieu d'un bloc d'instruction. En effet,
dans ce cas, le C dit de K&R, avait la sémantique curieuse
qu'il fallait allouer les variables locales déclarées
éventuellement dans le bloc mais s'il y avait des
initialisations, le compilateur n'était pas obligé de les
faire lors du branchement...
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Jean-Marc Bourguet a écrit :
> Wykaaa <wyk...@yahoo.fr> writes:
>> Jean-Marc Bourguet a écrit :
>>> Wykaaa <wyk...@yahoo.fr> writes:
>>>> Jean-Marc Bourguet a écrit :
>>>>> Wykaaa <wyk...@yahoo.fr> writes:
>>>>> Les tableaux C sont déjà une source de confusion assez grand e comme
>>>>> cela; faire croire que le nom d'un tableau a un type pointeur ne fa it
>>>>> qu'augmenter la confusion -- en particulier en C++.
>>>> Désolé, mais "un type pointeur", ça ne veut rien dire
>>>> puisque les pointeurs sont... typés.
>>> Bizarre, l'expression se trouve dans les normes C90,
>>> C++98, C99 et le dernier brouillon disponible de C++0X
>>> avec le sens que je lui donne ici.
>> La norme ne devrait pas dire "type pointeur", elle devrait
>> dire "de nature pointeur".
> Le mot est en italique dans la partie que j'ai regardé: la
> norme donne une définition du terme. Au même endroit
> qu'elle défini les autres types dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer
type" était en italique dns la référence que tu m'as fournie
plus loin.
>> De toute façon, il y a belle lurette que je ne fais pas
>> confiance à la norme pour le vocabulaire car il semble
>> qu'il n'a pas été porté une attention suffisante sur ce
>> point tout au long de la norme...
> C'est le moment de donner tes commentaires.
>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui
figurent dans le texte ne sont définis nulle part.
>>>> S'il n'y avait pas cette "équivalence" pointeur/tableau,
>>>> il n'y aurait pas besoin des [] pour indiquer à delete
>>>> que le pointeur pointe sur un tableau alloué
>>>> dynamiquement afin d'appeler les destructeurs pour chaque
>>>> instance.
>>> J'ai du mal à comprendre ce que tu veux dire. Dans
>>> int* t = new int[10];
>>> delete[] t;
>>> la conversion implicite d'un tableau en un pointeur
>>> n'intervient pas.
>> Certes mais il faut mettre les crochets car C, donc C++,
>> n'est pas capable de distinguer, de lui-même, entre un
>> pointeur sur variable scalaire et un pointeur sur tableau.
> Ne referais-tu pas la même erreur de nomenclature que celle
> qui a lancé cette discussion?
> int* x;
> int (*x)[10];
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
>> Il faut "l'aider", ce qui est anormal. Si le langage était
>> "bien fichu" il n'y aurait pas besoin de cette syntaxe pour
>> le moins bizarre. Il n'y a qu'à voir le nombre de questions
>> sur ce sujet dans les différents fora Internet.
>>>On la virerait et on permettrait d'appliquer [] sur les
>>>tableaux qu'il y a peu de choses qui changerait à part les
>>>appels de fonctions.
>> Oui mais les appels de fonction, c'est quand même important
>> non ?
> On aurait fait pour les tableaux ce qui a été fait pour les
> structures -- permettre le passage par valeur, être obligé
> d'utiliser & pour passer un pointeur -- il y aurait beaucoup
> de confusion en moins sans changer fondamentalement le
> rapport entre tableaux et pointeurs (dont la substantifique
> moelle est pour moi l'arithmétique sur les pointeurs).
Ben voilà. Ca serait déjà beaucoup mieux.
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type array of N T or array of
unknown bound of T can be converted to an rvalue of type
pointer to T. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
>> Par ailleurs, l'objectif de simplifier la conversion du
>> code B existant a été source d'autres mauvais choix comme
>> la priorité des opérateurs, en particulier pour les
>> opérateurs sur bits (&) par rapport à = ou ==.
> Ah ce qu'on garde par soucis de faciliter la transition même
> si ce n'est pas idéal et qu'il faudra vivre avec -- on le
> sait bien souvent au moment même ou on prend la décision,
> mais on a l'impression, souvent fondée, que c'est nécessaire
> pour vivre longtemps... et ce n'est pas propre au C (envers
> B et BCPL) et au C++ (envers le C) ni même aux langages ou à
> l'informatique.
En C, lors de la normalisation, on s'est bien débarrassé du
trait de langage très ennuyeux qui consistait à pouvoir faire
un branchement au milieu d'un bloc d'instruction. En effet,
dans ce cas, le C dit de K&R, avait la sémantique curieuse
qu'il fallait allouer les variables locales déclarées
éventuellement dans le bloc mais s'il y avait des
initialisations, le compilateur n'était pas obligé de les
faire lors du branchement...
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Jean-Marc Bourguet a écrit :
> Wykaaa writes:
>> Jean-Marc Bourguet a écrit :
>>> Wykaaa writes:
>>>> Jean-Marc Bourguet a écrit :
>>>>> Wykaaa writes:
>>>>> Les tableaux C sont déjà une source de confusion assez grand e comme
>>>>> cela; faire croire que le nom d'un tableau a un type pointeur ne fa it
>>>>> qu'augmenter la confusion -- en particulier en C++.
>>>> Désolé, mais "un type pointeur", ça ne veut rien dire
>>>> puisque les pointeurs sont... typés.
>>> Bizarre, l'expression se trouve dans les normes C90,
>>> C++98, C99 et le dernier brouillon disponible de C++0X
>>> avec le sens que je lui donne ici.
>> La norme ne devrait pas dire "type pointeur", elle devrait
>> dire "de nature pointeur".
> Le mot est en italique dans la partie que j'ai regardé: la
> norme donne une définition du terme. Au même endroit
> qu'elle défini les autres types dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer
type" était en italique dns la référence que tu m'as fournie
plus loin.
>> De toute façon, il y a belle lurette que je ne fais pas
>> confiance à la norme pour le vocabulaire car il semble
>> qu'il n'a pas été porté une attention suffisante sur ce
>> point tout au long de la norme...
> C'est le moment de donner tes commentaires.
>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui
figurent dans le texte ne sont définis nulle part.
>>>> S'il n'y avait pas cette "équivalence" pointeur/tableau,
>>>> il n'y aurait pas besoin des [] pour indiquer à delete
>>>> que le pointeur pointe sur un tableau alloué
>>>> dynamiquement afin d'appeler les destructeurs pour chaque
>>>> instance.
>>> J'ai du mal à comprendre ce que tu veux dire. Dans
>>> int* t = new int[10];
>>> delete[] t;
>>> la conversion implicite d'un tableau en un pointeur
>>> n'intervient pas.
>> Certes mais il faut mettre les crochets car C, donc C++,
>> n'est pas capable de distinguer, de lui-même, entre un
>> pointeur sur variable scalaire et un pointeur sur tableau.
> Ne referais-tu pas la même erreur de nomenclature que celle
> qui a lancé cette discussion?
> int* x;
> int (*x)[10];
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
>> Il faut "l'aider", ce qui est anormal. Si le langage était
>> "bien fichu" il n'y aurait pas besoin de cette syntaxe pour
>> le moins bizarre. Il n'y a qu'à voir le nombre de questions
>> sur ce sujet dans les différents fora Internet.
>>>On la virerait et on permettrait d'appliquer [] sur les
>>>tableaux qu'il y a peu de choses qui changerait à part les
>>>appels de fonctions.
>> Oui mais les appels de fonction, c'est quand même important
>> non ?
> On aurait fait pour les tableaux ce qui a été fait pour les
> structures -- permettre le passage par valeur, être obligé
> d'utiliser & pour passer un pointeur -- il y aurait beaucoup
> de confusion en moins sans changer fondamentalement le
> rapport entre tableaux et pointeurs (dont la substantifique
> moelle est pour moi l'arithmétique sur les pointeurs).
Ben voilà. Ca serait déjà beaucoup mieux.
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type array of N T or array of
unknown bound of T can be converted to an rvalue of type
pointer to T. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
>> Par ailleurs, l'objectif de simplifier la conversion du
>> code B existant a été source d'autres mauvais choix comme
>> la priorité des opérateurs, en particulier pour les
>> opérateurs sur bits (&) par rapport à = ou ==.
> Ah ce qu'on garde par soucis de faciliter la transition même
> si ce n'est pas idéal et qu'il faudra vivre avec -- on le
> sait bien souvent au moment même ou on prend la décision,
> mais on a l'impression, souvent fondée, que c'est nécessaire
> pour vivre longtemps... et ce n'est pas propre au C (envers
> B et BCPL) et au C++ (envers le C) ni même aux langages ou à
> l'informatique.
En C, lors de la normalisation, on s'est bien débarrassé du
trait de langage très ennuyeux qui consistait à pouvoir faire
un branchement au milieu d'un bloc d'instruction. En effet,
dans ce cas, le C dit de K&R, avait la sémantique curieuse
qu'il fallait allouer les variables locales déclarées
éventuellement dans le bloc mais s'il y avait des
initialisations, le compilateur n'était pas obligé de les
faire lors du branchement...
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Michael DOUBEZ a écrit :
[snip]
>> int* i = new int;
>> int* p = new int[10];
>> delete i;
>> delete [] p;
>> Pourquoi les [] seraient-ils nécessaires?
>> C'est cela que je voulais dire.
> Parce que la norme le dit en 5.3.4/5
Ca, ce n'est pas un argument. La vraie question est : pourquoi
est-ce nécessaire ?
Michael DOUBEZ a écrit :
[snip]
>> int* i = new int;
>> int* p = new int[10];
>> delete i;
>> delete [] p;
>> Pourquoi les [] seraient-ils nécessaires?
>> C'est cela que je voulais dire.
> Parce que la norme le dit en 5.3.4/5
Ca, ce n'est pas un argument. La vraie question est : pourquoi
est-ce nécessaire ?
Michael DOUBEZ a écrit :
[snip]
>> int* i = new int;
>> int* p = new int[10];
>> delete i;
>> delete [] p;
>> Pourquoi les [] seraient-ils nécessaires?
>> C'est cela que je voulais dire.
> Parce que la norme le dit en 5.3.4/5
Ca, ce n'est pas un argument. La vraie question est : pourquoi
est-ce nécessaire ?
On Nov 3, 1:45 pm, Wykaaa wrote:Jean-Marc Bourguet a écrit :Wykaaa writes:Jean-Marc Bourguet a écrit :Wykaaa writes:Jean-Marc Bourguet a écrit :Wykaaa writes:
Les tableaux C sont déjà une source de confusion assez grande comme
cela; faire croire que le nom d'un tableau a un type pointeur ne fait
qu'augmenter la confusion -- en particulier en C++.
Désolé, mais "un type pointeur", ça ne veut rien dire
puisque les pointeurs sont... typés.
Bizarre, l'expression se trouve dans les normes C90,
C++98, C99 et le dernier brouillon disponible de C++0X
avec le sens que je lui donne ici.
La norme ne devrait pas dire "type pointeur", elle devrait
dire "de nature pointeur".Le mot est en italique dans la partie que j'ai regardé: la
norme donne une définition du terme. Au même endroit
qu'elle défini les autres types dérivés.J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer
type" était en italique dns la référence que tu m'as fournie
plus loin.
C'est vrai que dans la définition (§3.9.2), elle parle de
« pointers », et non « pointer types », mais vu le nom de la
section (« Composite types »), je crois que c'est clair que ce
dont elle parle ici, ce sont des types pointeur (et non des
variables pointeurs, etc.).
De toute façon, il y a belle lurette que je ne fais pas
confiance à la norme pour le vocabulaire car il semble
qu'il n'a pas été porté une attention suffisante sur ce
point tout au long de la norme...C'est le moment de donner tes commentaires.http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdfPffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui
figurent dans le texte ne sont définis nulle part.
En tant qu'annex, je suis bien d'accord. Tu te portes volentaire
pour le réaliser ?
[...]S'il n'y avait pas cette "équivalence" pointeur/tableau,
il n'y aurait pas besoin des [] pour indiquer à delete
que le pointeur pointe sur un tableau alloué
dynamiquement afin d'appeler les destructeurs pour chaque
instance.
J'ai du mal à comprendre ce que tu veux dire. Dansint* t = new int[10];
delete[] t;la conversion implicite d'un tableau en un pointeur
n'intervient pas.
Certes mais il faut mettre les crochets car C, donc C++,
n'est pas capable de distinguer, de lui-même, entre un
pointeur sur variable scalaire et un pointeur sur tableau.
C'est parce qu'ici, il n'y a pas de pointeur sur tableau.Ne referais-tu pas la même erreur de nomenclature que celle
qui a lancé cette discussion?int* x;int (*x)[10];int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
Il faut "l'aider", ce qui est anormal. Si le langage était
"bien fichu" il n'y aurait pas besoin de cette syntaxe pour
le moins bizarre. Il n'y a qu'à voir le nombre de questions
sur ce sujet dans les différents fora Internet.On la virerait et on permettrait d'appliquer [] sur les
tableaux qu'il y a peu de choses qui changerait à part les
appels de fonctions.
Oui mais les appels de fonction, c'est quand même important
non ?On aurait fait pour les tableaux ce qui a été fait pour les
structures -- permettre le passage par valeur, être obligé
d'utiliser & pour passer un pointeur -- il y aurait beaucoup
de confusion en moins sans changer fondamentalement le
rapport entre tableaux et pointeurs (dont la substantifique
moelle est pour moi l'arithmétique sur les pointeurs).Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
Par ailleurs, l'objectif de simplifier la conversion du
code B existant a été source d'autres mauvais choix comme
la priorité des opérateurs, en particulier pour les
opérateurs sur bits (&) par rapport à = ou ==.Ah ce qu'on garde par soucis de faciliter la transition même
si ce n'est pas idéal et qu'il faudra vivre avec -- on le
sait bien souvent au moment même ou on prend la décision,
mais on a l'impression, souvent fondée, que c'est nécessaire
pour vivre longtemps... et ce n'est pas propre au C (envers
B et BCPL) et au C++ (envers le C) ni même aux langages ou à
l'informatique.En C, lors de la normalisation, on s'est bien débarrassé du
trait de langage très ennuyeux qui consistait à pouvoir faire
un branchement au milieu d'un bloc d'instruction. En effet,
dans ce cas, le C dit de K&R, avait la sémantique curieuse
qu'il fallait allouer les variables locales déclarées
éventuellement dans le bloc mais s'il y avait des
initialisations, le compilateur n'était pas obligé de les
faire lors du branchement...
J'ai dû mal comprendre. J'ai l'impression que tu dis qu'on s'est
débarrassé de quelque chose comme :
void
f()
{
goto toto ;
{
int i ;
toto:
i = 43 ;
}
}
Or, c'est un programme on ne peut plus légal. (Pas beau du tout,
mais légal, quand même.)
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
On Nov 3, 1:45 pm, Wykaaa <wyk...@yahoo.fr> wrote:
Jean-Marc Bourguet a écrit :
Wykaaa <wyk...@yahoo.fr> writes:
Jean-Marc Bourguet a écrit :
Wykaaa <wyk...@yahoo.fr> writes:
Jean-Marc Bourguet a écrit :
Wykaaa <wyk...@yahoo.fr> writes:
Les tableaux C sont déjà une source de confusion assez grande comme
cela; faire croire que le nom d'un tableau a un type pointeur ne fait
qu'augmenter la confusion -- en particulier en C++.
Désolé, mais "un type pointeur", ça ne veut rien dire
puisque les pointeurs sont... typés.
Bizarre, l'expression se trouve dans les normes C90,
C++98, C99 et le dernier brouillon disponible de C++0X
avec le sens que je lui donne ici.
La norme ne devrait pas dire "type pointeur", elle devrait
dire "de nature pointeur".
Le mot est en italique dans la partie que j'ai regardé: la
norme donne une définition du terme. Au même endroit
qu'elle défini les autres types dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer
type" était en italique dns la référence que tu m'as fournie
plus loin.
C'est vrai que dans la définition (§3.9.2), elle parle de
« pointers », et non « pointer types », mais vu le nom de la
section (« Composite types »), je crois que c'est clair que ce
dont elle parle ici, ce sont des types pointeur (et non des
variables pointeurs, etc.).
De toute façon, il y a belle lurette que je ne fais pas
confiance à la norme pour le vocabulaire car il semble
qu'il n'a pas été porté une attention suffisante sur ce
point tout au long de la norme...
C'est le moment de donner tes commentaires.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui
figurent dans le texte ne sont définis nulle part.
En tant qu'annex, je suis bien d'accord. Tu te portes volentaire
pour le réaliser ?
[...]
S'il n'y avait pas cette "équivalence" pointeur/tableau,
il n'y aurait pas besoin des [] pour indiquer à delete
que le pointeur pointe sur un tableau alloué
dynamiquement afin d'appeler les destructeurs pour chaque
instance.
J'ai du mal à comprendre ce que tu veux dire. Dans
int* t = new int[10];
delete[] t;
la conversion implicite d'un tableau en un pointeur
n'intervient pas.
Certes mais il faut mettre les crochets car C, donc C++,
n'est pas capable de distinguer, de lui-même, entre un
pointeur sur variable scalaire et un pointeur sur tableau.
C'est parce qu'ici, il n'y a pas de pointeur sur tableau.
Ne referais-tu pas la même erreur de nomenclature que celle
qui a lancé cette discussion?
int* x;
int (*x)[10];
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
Il faut "l'aider", ce qui est anormal. Si le langage était
"bien fichu" il n'y aurait pas besoin de cette syntaxe pour
le moins bizarre. Il n'y a qu'à voir le nombre de questions
sur ce sujet dans les différents fora Internet.
On la virerait et on permettrait d'appliquer [] sur les
tableaux qu'il y a peu de choses qui changerait à part les
appels de fonctions.
Oui mais les appels de fonction, c'est quand même important
non ?
On aurait fait pour les tableaux ce qui a été fait pour les
structures -- permettre le passage par valeur, être obligé
d'utiliser & pour passer un pointeur -- il y aurait beaucoup
de confusion en moins sans changer fondamentalement le
rapport entre tableaux et pointeurs (dont la substantifique
moelle est pour moi l'arithmétique sur les pointeurs).
Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
Par ailleurs, l'objectif de simplifier la conversion du
code B existant a été source d'autres mauvais choix comme
la priorité des opérateurs, en particulier pour les
opérateurs sur bits (&) par rapport à = ou ==.
Ah ce qu'on garde par soucis de faciliter la transition même
si ce n'est pas idéal et qu'il faudra vivre avec -- on le
sait bien souvent au moment même ou on prend la décision,
mais on a l'impression, souvent fondée, que c'est nécessaire
pour vivre longtemps... et ce n'est pas propre au C (envers
B et BCPL) et au C++ (envers le C) ni même aux langages ou à
l'informatique.
En C, lors de la normalisation, on s'est bien débarrassé du
trait de langage très ennuyeux qui consistait à pouvoir faire
un branchement au milieu d'un bloc d'instruction. En effet,
dans ce cas, le C dit de K&R, avait la sémantique curieuse
qu'il fallait allouer les variables locales déclarées
éventuellement dans le bloc mais s'il y avait des
initialisations, le compilateur n'était pas obligé de les
faire lors du branchement...
J'ai dû mal comprendre. J'ai l'impression que tu dis qu'on s'est
débarrassé de quelque chose comme :
void
f()
{
goto toto ;
{
int i ;
toto:
i = 43 ;
}
}
Or, c'est un programme on ne peut plus légal. (Pas beau du tout,
mais légal, quand même.)
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
On Nov 3, 1:45 pm, Wykaaa wrote:Jean-Marc Bourguet a écrit :Wykaaa writes:Jean-Marc Bourguet a écrit :Wykaaa writes:Jean-Marc Bourguet a écrit :Wykaaa writes:
Les tableaux C sont déjà une source de confusion assez grande comme
cela; faire croire que le nom d'un tableau a un type pointeur ne fait
qu'augmenter la confusion -- en particulier en C++.
Désolé, mais "un type pointeur", ça ne veut rien dire
puisque les pointeurs sont... typés.
Bizarre, l'expression se trouve dans les normes C90,
C++98, C99 et le dernier brouillon disponible de C++0X
avec le sens que je lui donne ici.
La norme ne devrait pas dire "type pointeur", elle devrait
dire "de nature pointeur".Le mot est en italique dans la partie que j'ai regardé: la
norme donne une définition du terme. Au même endroit
qu'elle défini les autres types dérivés.J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer
type" était en italique dns la référence que tu m'as fournie
plus loin.
C'est vrai que dans la définition (§3.9.2), elle parle de
« pointers », et non « pointer types », mais vu le nom de la
section (« Composite types »), je crois que c'est clair que ce
dont elle parle ici, ce sont des types pointeur (et non des
variables pointeurs, etc.).
De toute façon, il y a belle lurette que je ne fais pas
confiance à la norme pour le vocabulaire car il semble
qu'il n'a pas été porté une attention suffisante sur ce
point tout au long de la norme...C'est le moment de donner tes commentaires.http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdfPffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui
figurent dans le texte ne sont définis nulle part.
En tant qu'annex, je suis bien d'accord. Tu te portes volentaire
pour le réaliser ?
[...]S'il n'y avait pas cette "équivalence" pointeur/tableau,
il n'y aurait pas besoin des [] pour indiquer à delete
que le pointeur pointe sur un tableau alloué
dynamiquement afin d'appeler les destructeurs pour chaque
instance.
J'ai du mal à comprendre ce que tu veux dire. Dansint* t = new int[10];
delete[] t;la conversion implicite d'un tableau en un pointeur
n'intervient pas.
Certes mais il faut mettre les crochets car C, donc C++,
n'est pas capable de distinguer, de lui-même, entre un
pointeur sur variable scalaire et un pointeur sur tableau.
C'est parce qu'ici, il n'y a pas de pointeur sur tableau.Ne referais-tu pas la même erreur de nomenclature que celle
qui a lancé cette discussion?int* x;int (*x)[10];int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
Il faut "l'aider", ce qui est anormal. Si le langage était
"bien fichu" il n'y aurait pas besoin de cette syntaxe pour
le moins bizarre. Il n'y a qu'à voir le nombre de questions
sur ce sujet dans les différents fora Internet.On la virerait et on permettrait d'appliquer [] sur les
tableaux qu'il y a peu de choses qui changerait à part les
appels de fonctions.
Oui mais les appels de fonction, c'est quand même important
non ?On aurait fait pour les tableaux ce qui a été fait pour les
structures -- permettre le passage par valeur, être obligé
d'utiliser & pour passer un pointeur -- il y aurait beaucoup
de confusion en moins sans changer fondamentalement le
rapport entre tableaux et pointeurs (dont la substantifique
moelle est pour moi l'arithmétique sur les pointeurs).Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
Par ailleurs, l'objectif de simplifier la conversion du
code B existant a été source d'autres mauvais choix comme
la priorité des opérateurs, en particulier pour les
opérateurs sur bits (&) par rapport à = ou ==.Ah ce qu'on garde par soucis de faciliter la transition même
si ce n'est pas idéal et qu'il faudra vivre avec -- on le
sait bien souvent au moment même ou on prend la décision,
mais on a l'impression, souvent fondée, que c'est nécessaire
pour vivre longtemps... et ce n'est pas propre au C (envers
B et BCPL) et au C++ (envers le C) ni même aux langages ou à
l'informatique.En C, lors de la normalisation, on s'est bien débarrassé du
trait de langage très ennuyeux qui consistait à pouvoir faire
un branchement au milieu d'un bloc d'instruction. En effet,
dans ce cas, le C dit de K&R, avait la sémantique curieuse
qu'il fallait allouer les variables locales déclarées
éventuellement dans le bloc mais s'il y avait des
initialisations, le compilateur n'était pas obligé de les
faire lors du branchement...
J'ai dû mal comprendre. J'ai l'impression que tu dis qu'on s'est
débarrassé de quelque chose comme :
void
f()
{
goto toto ;
{
int i ;
toto:
i = 43 ;
}
}
Or, c'est un programme on ne peut plus légal. (Pas beau du tout,
mais légal, quand même.)
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Jean-Marc Bourguet a écrit :
> Le mot est en italique dans la partie que j'ai regardé: la norme donne une
> définition du terme. Au même endroit qu'elle défini les autres types
> dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer type" était en
italique dns la référence que tu m'as fournie plus loin.
>> De toute façon, il y a belle lurette que je ne fais pas confiance à la
>> norme pour le vocabulaire car il semble qu'il n'a pas été porté une
>> attention suffisante sur ce point tout au long de la norme...
> C'est le moment de donner tes commentaires.
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui figurent dans le
texte ne sont définis nulle part.
> Ne referais-tu pas la même erreur de nomenclature que celle qui a lancé
> cette discussion?
> int* x;
> int (*x)[10];
>
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Ben voilà. Ca serait déjà beaucoup mieux.
Qu'on le veuille ou non, la conversion d'un nom de tableau en pointeur sur
son premier élément est bien im-pli-cite et, donc, standard.
Jean-Marc Bourguet a écrit :
> Le mot est en italique dans la partie que j'ai regardé: la norme donne une
> définition du terme. Au même endroit qu'elle défini les autres types
> dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer type" était en
italique dns la référence que tu m'as fournie plus loin.
>> De toute façon, il y a belle lurette que je ne fais pas confiance à la
>> norme pour le vocabulaire car il semble qu'il n'a pas été porté une
>> attention suffisante sur ce point tout au long de la norme...
> C'est le moment de donner tes commentaires.
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui figurent dans le
texte ne sont définis nulle part.
> Ne referais-tu pas la même erreur de nomenclature que celle qui a lancé
> cette discussion?
> int* x;
> int (*x)[10];
>
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Ben voilà. Ca serait déjà beaucoup mieux.
Qu'on le veuille ou non, la conversion d'un nom de tableau en pointeur sur
son premier élément est bien im-pli-cite et, donc, standard.
Jean-Marc Bourguet a écrit :
> Le mot est en italique dans la partie que j'ai regardé: la norme donne une
> définition du terme. Au même endroit qu'elle défini les autres types
> dérivés.
J'ai cherché... et je n'ai pas trouvé d'endroit où "pointer type" était en
italique dns la référence que tu m'as fournie plus loin.
>> De toute façon, il y a belle lurette que je ne fais pas confiance à la
>> norme pour le vocabulaire car il semble qu'il n'a pas été porté une
>> attention suffisante sur ce point tout au long de la norme...
> C'est le moment de donner tes commentaires.
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf
Pffft : 1350 pages, je n'ai pas le courage...
Il n'y a pas de vrai glossaire C++ dans la norme. C'est très
regrettable. Quantité de termes apparemment techniques qui figurent dans le
texte ne sont définis nulle part.
> Ne referais-tu pas la même erreur de nomenclature que celle qui a lancé
> cette discussion?
> int* x;
> int (*x)[10];
>
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Ben voilà. Ca serait déjà beaucoup mieux.
Qu'on le veuille ou non, la conversion d'un nom de tableau en pointeur sur
son premier élément est bien im-pli-cite et, donc, standard.
James Kanze a écrit :On Nov 3, 1:45 pm, Wykaaa wrote:
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est
la raison à l'origine de cette décision ?
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des crochets
pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le tableau
alloué dynamiquement.
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur un
tableau.
Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands
de tapis".
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
C'est le moins qu'on puisse dire !Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour être
"propre", il faudrait donc transformer toutes les utilisations des
tableaux C en vector lors du passage de C à C++ ou ne jamais utiliser
les tableaux C en C++. Dans ce cas, ça ne servait à rien de conserver la
compatibilité...
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça se
voit !). Il aurait dû resté interne aux Bell Labs...
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des expressions
comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5) car +
est plus prioritaire que &, ce qui est une grosse erreur de conception
du langage.
De toute façon, K&R étaient très bons en système mais assez nuls en
langage (comme souvent chez les "hommes système").
James Kanze a écrit :
On Nov 3, 1:45 pm, Wykaaa <wyk...@yahoo.fr> wrote:
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est
la raison à l'origine de cette décision ?
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des crochets
pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le tableau
alloué dynamiquement.
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur un
tableau.
Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands
de tapis".
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
C'est le moins qu'on puisse dire !
Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour être
"propre", il faudrait donc transformer toutes les utilisations des
tableaux C en vector lors du passage de C à C++ ou ne jamais utiliser
les tableaux C en C++. Dans ce cas, ça ne servait à rien de conserver la
compatibilité...
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça se
voit !). Il aurait dû resté interne aux Bell Labs...
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des expressions
comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5) car +
est plus prioritaire que &, ce qui est une grosse erreur de conception
du langage.
De toute façon, K&R étaient très bons en système mais assez nuls en
langage (comme souvent chez les "hommes système").
James Kanze a écrit :On Nov 3, 1:45 pm, Wykaaa wrote:
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est
la raison à l'origine de cette décision ?
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des crochets
pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le tableau
alloué dynamiquement.
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur un
tableau.
Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands
de tapis".
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
C'est le moins qu'on puisse dire !Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour être
"propre", il faudrait donc transformer toutes les utilisations des
tableaux C en vector lors du passage de C à C++ ou ne jamais utiliser
les tableaux C en C++. Dans ce cas, ça ne servait à rien de conserver la
compatibilité...
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça se
voit !). Il aurait dû resté interne aux Bell Labs...
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des expressions
comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5) car +
est plus prioritaire que &, ce qui est une grosse erreur de conception
du langage.
De toute façon, K&R étaient très bons en système mais assez nuls en
langage (comme souvent chez les "hommes système").
Wykaaa a écrit :James Kanze a écrit :On Nov 3, 1:45 pm, Wykaaa wrote:
[snip]int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est
la raison à l'origine de cette décision ?
Je suppose que ça viens du même problème que la conversion implicite: si
j'écris une fonction pour effacer un tableau de taille inconnue, je dois
passer le tableau en paramètre et donc il passe par pointeur. Il faut
donc bien un moyen de signifier à delete qu'il s'agit d'un tableau:
void dispose_of(int* table)
{
delete[] table;
}
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des
crochets pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Auquel je préfère:
scoped_ptr<Client> cli(new Client);Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le
tableau alloué dynamiquement.
Auquel je substitue:
scoped_array<Client> cli(new Client [10]);
Nous sommes d'accord que toute dépendance est source de problème. C'est
bien pour ça que C++0x donne tout un ensemble d'outils pour rendre la
vie plus facile (auto,decltype ...)Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur
un tableau.
Accepté par le compilateur peut être. Ce genre de chose est impossible à
vérifier à la compilation.
[snip]Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands
de tapis".
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
C'est le moins qu'on puisse dire !Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour
être "propre", il faudrait donc transformer toutes les utilisations
des tableaux C en vector lors du passage de C à C++ ou ne jamais
utiliser les tableaux C en C++. Dans ce cas, ça ne servait à rien de
conserver la compatibilité...
Ce qui pose la question des VLAs pour C++0x. Je comprends que ça puisse
rendre la vie de compilateurs plus difficile mais c'est AMA là où il y a
le plus de travail quand on porte du code C99 vers C++ (ou quand le code
à été écrit sur un compilateur souple).
[snip]Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Oui. Un tableau a un type 'tableau' et un pointeur a un type 'pointeur'.
Qu'il y ait une conversion implicite et qu'on puisse utiliser
l'opérateur [] avec un pointeur ne crée pas une identité des types.
[snip]Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça
se voit !). Il aurait dû resté interne aux Bell Labs...
Le C et les autres langages /brackets/ sont aujourd'hui ceux
principalement utilisées dans l'industrie. Pas forcément les plus
adaptés et les plus visuellement plaisant mais l'establishment est là;
ça leur donne quand même une certaine valeur.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des expressions
comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5) car
+ est plus prioritaire que &, ce qui est une grosse erreur de
conception du langage.
Mais ça permet d'écrire:
if( a < b+1 & a > c ) ...
Et ça aurait peut être causé plus de confusion si ça n'avait pas été
interchangeable avec:
if( a < b+1 && a > c )...
De toute façon, K&R étaient très bons en système mais assez nuls en
langage (comme souvent chez les "hommes système").
Des langages comme fortran, cobol, algol ou lisp n'étaient pas non plus
adaptés à la programmation système.
Concernant les "hommes système", je ne sais pas, je ne suis pas
spécialiste, mais je pense qu'en ce qui concerne K&R, ils ont créé un
langage adapté à leur besoin.
AMA la théorie du langage se heurte parfois au mur de la réalité et
reproche juste au mur d'être un peu trop solide :)
Wykaaa a écrit :
James Kanze a écrit :
On Nov 3, 1:45 pm, Wykaaa <wyk...@yahoo.fr> wrote:
[snip]
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est
la raison à l'origine de cette décision ?
Je suppose que ça viens du même problème que la conversion implicite: si
j'écris une fonction pour effacer un tableau de taille inconnue, je dois
passer le tableau en paramètre et donc il passe par pointeur. Il faut
donc bien un moyen de signifier à delete qu'il s'agit d'un tableau:
void dispose_of(int* table)
{
delete[] table;
}
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des
crochets pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Auquel je préfère:
scoped_ptr<Client> cli(new Client);
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le
tableau alloué dynamiquement.
Auquel je substitue:
scoped_array<Client> cli(new Client [10]);
Nous sommes d'accord que toute dépendance est source de problème. C'est
bien pour ça que C++0x donne tout un ensemble d'outils pour rendre la
vie plus facile (auto,decltype ...)
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur
un tableau.
Accepté par le compilateur peut être. Ce genre de chose est impossible à
vérifier à la compilation.
[snip]
Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands
de tapis".
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
C'est le moins qu'on puisse dire !
Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour
être "propre", il faudrait donc transformer toutes les utilisations
des tableaux C en vector lors du passage de C à C++ ou ne jamais
utiliser les tableaux C en C++. Dans ce cas, ça ne servait à rien de
conserver la compatibilité...
Ce qui pose la question des VLAs pour C++0x. Je comprends que ça puisse
rendre la vie de compilateurs plus difficile mais c'est AMA là où il y a
le plus de travail quand on porte du code C99 vers C++ (ou quand le code
à été écrit sur un compilateur souple).
[snip]
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Oui. Un tableau a un type 'tableau' et un pointeur a un type 'pointeur'.
Qu'il y ait une conversion implicite et qu'on puisse utiliser
l'opérateur [] avec un pointeur ne crée pas une identité des types.
[snip]
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça
se voit !). Il aurait dû resté interne aux Bell Labs...
Le C et les autres langages /brackets/ sont aujourd'hui ceux
principalement utilisées dans l'industrie. Pas forcément les plus
adaptés et les plus visuellement plaisant mais l'establishment est là;
ça leur donne quand même une certaine valeur.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des expressions
comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5) car
+ est plus prioritaire que &, ce qui est une grosse erreur de
conception du langage.
Mais ça permet d'écrire:
if( a < b+1 & a > c ) ...
Et ça aurait peut être causé plus de confusion si ça n'avait pas été
interchangeable avec:
if( a < b+1 && a > c )...
De toute façon, K&R étaient très bons en système mais assez nuls en
langage (comme souvent chez les "hommes système").
Des langages comme fortran, cobol, algol ou lisp n'étaient pas non plus
adaptés à la programmation système.
Concernant les "hommes système", je ne sais pas, je ne suis pas
spécialiste, mais je pense qu'en ce qui concerne K&R, ils ont créé un
langage adapté à leur besoin.
AMA la théorie du langage se heurte parfois au mur de la réalité et
reproche juste au mur d'être un peu trop solide :)
Wykaaa a écrit :James Kanze a écrit :On Nov 3, 1:45 pm, Wykaaa wrote:
[snip]int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est
la raison à l'origine de cette décision ?
Je suppose que ça viens du même problème que la conversion implicite: si
j'écris une fonction pour effacer un tableau de taille inconnue, je dois
passer le tableau en paramètre et donc il passe par pointeur. Il faut
donc bien un moyen de signifier à delete qu'il s'agit d'un tableau:
void dispose_of(int* table)
{
delete[] table;
}
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des
crochets pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Auquel je préfère:
scoped_ptr<Client> cli(new Client);Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le
tableau alloué dynamiquement.
Auquel je substitue:
scoped_array<Client> cli(new Client [10]);
Nous sommes d'accord que toute dépendance est source de problème. C'est
bien pour ça que C++0x donne tout un ensemble d'outils pour rendre la
vie plus facile (auto,decltype ...)Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur
un tableau.
Accepté par le compilateur peut être. Ce genre de chose est impossible à
vérifier à la compilation.
[snip]Ben voilà. Ca serait déjà beaucoup mieux.
Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands
de tapis".
On en a discuté dans le comité de normalisation. Tout le monde
était d'accord que les tableaux de type C, c'est un désastre.
C'est le moins qu'on puisse dire !Seulement, comment l'améliorer sans briser la comptabilité C. À
la fin, la décision était de les laisser tels quels, en
fournissant des altérnatifs nouveaux supérieur (genre
std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour
être "propre", il faudrait donc transformer toutes les utilisations
des tableaux C en vector lors du passage de C à C++ ou ne jamais
utiliser les tableaux C en C++. Dans ce cas, ça ne servait à rien de
conserver la compatibilité...
Ce qui pose la question des VLAs pour C++0x. Je comprends que ça puisse
rendre la vie de compilateurs plus difficile mais c'est AMA là où il y a
le plus de travail quand on porte du code C99 vers C++ (ou quand le code
à été écrit sur un compilateur souple).
[snip]Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Oui. Un tableau a un type 'tableau' et un pointeur a un type 'pointeur'.
Qu'il y ait une conversion implicite et qu'on puisse utiliser
l'opérateur [] avec un pointeur ne crée pas une identité des types.
[snip]Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça
se voit !). Il aurait dû resté interne aux Bell Labs...
Le C et les autres langages /brackets/ sont aujourd'hui ceux
principalement utilisées dans l'industrie. Pas forcément les plus
adaptés et les plus visuellement plaisant mais l'establishment est là;
ça leur donne quand même une certaine valeur.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des expressions
comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5) car
+ est plus prioritaire que &, ce qui est une grosse erreur de
conception du langage.
Mais ça permet d'écrire:
if( a < b+1 & a > c ) ...
Et ça aurait peut être causé plus de confusion si ça n'avait pas été
interchangeable avec:
if( a < b+1 && a > c )...
De toute façon, K&R étaient très bons en système mais assez nuls en
langage (comme souvent chez les "hommes système").
Des langages comme fortran, cobol, algol ou lisp n'étaient pas non plus
adaptés à la programmation système.
Concernant les "hommes système", je ne sais pas, je ne suis pas
spécialiste, mais je pense qu'en ce qui concerne K&R, ils ont créé un
langage adapté à leur besoin.
AMA la théorie du langage se heurte parfois au mur de la réalité et
reproche juste au mur d'être un peu trop solide :)
Michael DOUBEZ a écrit :Wykaaa a écrit :James Kanze a écrit :On Nov 3, 1:45 pm, Wykaaa wrote:
[snip]int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle
est la raison à l'origine de cette décision ?
Je suppose que ça viens du même problème que la conversion implicite:
si j'écris une fonction pour effacer un tableau de taille inconnue, je
dois passer le tableau en paramètre et donc il passe par pointeur. Il
faut donc bien un moyen de signifier à delete qu'il s'agit d'un tableau:
void dispose_of(int* table)
{
delete[] table;
}
Ce n'est pas un bon exemple car ici c'est un tableau de int qui ne sont
pas des instances de classe.
Les [] dans delete sont là pour que le
destructeur des instances de la classe soit appelé sur chacun des
éléments du tableau.
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des
crochets pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Auquel je préfère:
scoped_ptr<Client> cli(new Client);Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le
tableau alloué dynamiquement.
Auquel je substitue:
scoped_array<Client> cli(new Client [10]);
Donc, du coup on voit que la discipline de programmation en C++ esttrès
éloignée de celle du C; Ce n'était donc pas la peine, lors de la
normalisation, de conserver une "compatibilité à tout prix" avec le C,
puisque, pour écrire "propre" en C++, on n'utilise pratiquement plus
aucun trait de C, au moins pour les tableaux et pointeurs...
On voit donc que la préservation de la compatibilité avec C a eu des
effets plutôt néfastes puisqu'il faut développer, en C++, tout un
ensemble d'outils pour pallier les déficiences du langage C qu'on a
voulu conserver coûte que coûte en C++, pour finalement dire qu'il ne
faut pas les utiliser.
Tout ceci est totalement absurde et rend le langage C++, de loin le
langage le plus abscon de tous les langages de programmation (c'est
quand même le seul langage qui a réussi à inventé des mots clés avec des
underscores !)
Nous sommes d'accord que toute dépendance est source de problème.
C'est bien pour ça que C++0x donne tout un ensemble d'outils pour
rendre la vie plus facile (auto,decltype ...)Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur
un tableau.
Accepté par le compilateur peut être. Ce genre de chose est impossible
à vérifier à la compilation.
Ben si, si on prend la peine d'ajouter des informations sur les
pointeurs...
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Oui. Un tableau a un type 'tableau' et un pointeur a un type
'pointeur'. Qu'il y ait une conversion implicite et qu'on puisse
utiliser l'opérateur [] avec un pointeur ne crée pas une identité des
types.
Non pas identité, ce qui n'a jamais été dit, mais équivalence (de par la
conversion implicite justement). Du point de vue de la sémantique
identité et équivalence ne sont pas des termes... équivalents !
[snip]Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça
se voit !). Il aurait dû resté interne aux Bell Labs...
Le C et les autres langages /brackets/ sont aujourd'hui ceux
principalement utilisées dans l'industrie. Pas forcément les plus
adaptés et les plus visuellement plaisant mais l'establishment est là;
ça leur donne quand même une certaine valeur.
Le langage C ne doit sa popularité qu'au succès d'Unix car le couple
C-Unix est l'équivalent (du moins dans le monde système) de l'ancien
couple PL/1-Multics.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des
expressions comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5)
car + est plus prioritaire que &, ce qui est une grosse erreur de
conception du langage.
Mais ça permet d'écrire:
if( a < b+1 & a > c ) ...
Et ça aurait peut être causé plus de confusion si ça n'avait pas été
interchangeable avec:
if( a < b+1 && a > c )...
Avoue que l'interchangeabilité de ces deux expressions n'est
certainement pas essentielle en développement.
Ici, on a parlé surtout des confusions occasionnées par les tableaux,
les pointeurs et le mauvais choix de la priorité des opérateurs en
langage C...
Michael DOUBEZ a écrit :
Wykaaa a écrit :
James Kanze a écrit :
On Nov 3, 1:45 pm, Wykaaa <wyk...@yahoo.fr> wrote:
[snip]
int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle
est la raison à l'origine de cette décision ?
Je suppose que ça viens du même problème que la conversion implicite:
si j'écris une fonction pour effacer un tableau de taille inconnue, je
dois passer le tableau en paramètre et donc il passe par pointeur. Il
faut donc bien un moyen de signifier à delete qu'il s'agit d'un tableau:
void dispose_of(int* table)
{
delete[] table;
}
Ce n'est pas un bon exemple car ici c'est un tableau de int qui ne sont
pas des instances de classe.
Les [] dans delete sont là pour que le
destructeur des instances de la classe soit appelé sur chacun des
éléments du tableau.
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des
crochets pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Auquel je préfère:
scoped_ptr<Client> cli(new Client);
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le
tableau alloué dynamiquement.
Auquel je substitue:
scoped_array<Client> cli(new Client [10]);
Donc, du coup on voit que la discipline de programmation en C++ esttrès
éloignée de celle du C; Ce n'était donc pas la peine, lors de la
normalisation, de conserver une "compatibilité à tout prix" avec le C,
puisque, pour écrire "propre" en C++, on n'utilise pratiquement plus
aucun trait de C, au moins pour les tableaux et pointeurs...
On voit donc que la préservation de la compatibilité avec C a eu des
effets plutôt néfastes puisqu'il faut développer, en C++, tout un
ensemble d'outils pour pallier les déficiences du langage C qu'on a
voulu conserver coûte que coûte en C++, pour finalement dire qu'il ne
faut pas les utiliser.
Tout ceci est totalement absurde et rend le langage C++, de loin le
langage le plus abscon de tous les langages de programmation (c'est
quand même le seul langage qui a réussi à inventé des mots clés avec des
underscores !)
Nous sommes d'accord que toute dépendance est source de problème.
C'est bien pour ça que C++0x donne tout un ensemble d'outils pour
rendre la vie plus facile (auto,decltype ...)
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur
un tableau.
Accepté par le compilateur peut être. Ce genre de chose est impossible
à vérifier à la compilation.
Ben si, si on prend la peine d'ajouter des informations sur les
pointeurs...
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Oui. Un tableau a un type 'tableau' et un pointeur a un type
'pointeur'. Qu'il y ait une conversion implicite et qu'on puisse
utiliser l'opérateur [] avec un pointeur ne crée pas une identité des
types.
Non pas identité, ce qui n'a jamais été dit, mais équivalence (de par la
conversion implicite justement). Du point de vue de la sémantique
identité et équivalence ne sont pas des termes... équivalents !
[snip]
Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça
se voit !). Il aurait dû resté interne aux Bell Labs...
Le C et les autres langages /brackets/ sont aujourd'hui ceux
principalement utilisées dans l'industrie. Pas forcément les plus
adaptés et les plus visuellement plaisant mais l'establishment est là;
ça leur donne quand même une certaine valeur.
Le langage C ne doit sa popularité qu'au succès d'Unix car le couple
C-Unix est l'équivalent (du moins dans le monde système) de l'ancien
couple PL/1-Multics.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des
expressions comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5)
car + est plus prioritaire que &, ce qui est une grosse erreur de
conception du langage.
Mais ça permet d'écrire:
if( a < b+1 & a > c ) ...
Et ça aurait peut être causé plus de confusion si ça n'avait pas été
interchangeable avec:
if( a < b+1 && a > c )...
Avoue que l'interchangeabilité de ces deux expressions n'est
certainement pas essentielle en développement.
Ici, on a parlé surtout des confusions occasionnées par les tableaux,
les pointeurs et le mauvais choix de la priorité des opérateurs en
langage C...
Michael DOUBEZ a écrit :Wykaaa a écrit :James Kanze a écrit :On Nov 3, 1:45 pm, Wykaaa wrote:
[snip]int* i = new int;
int* p = new int[10];
delete i;
delete [] p;
Pourquoi les [] seraient-ils nécessaires?
C'est cela que je voulais dire.
Parce que la norme l'exige. Il n'y a pas d'autre raison. La
norme distingue deux types d'opérateur new qui renvoient un T*,
selon le type alloué. Et donc, deux types d'opérateur delete.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle
est la raison à l'origine de cette décision ?
Je suppose que ça viens du même problème que la conversion implicite:
si j'écris une fonction pour effacer un tableau de taille inconnue, je
dois passer le tableau en paramètre et donc il passe par pointeur. Il
faut donc bien un moyen de signifier à delete qu'il s'agit d'un tableau:
void dispose_of(int* table)
{
delete[] table;
}
Ce n'est pas un bon exemple car ici c'est un tableau de int qui ne sont
pas des instances de classe.
Les [] dans delete sont là pour que le
destructeur des instances de la classe soit appelé sur chacun des
éléments du tableau.
C'est bête, mais dans la pratique, je ne me suis jamais servi
d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des
crochets pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Auquel je préfère:
scoped_ptr<Client> cli(new Client);Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le
tableau alloué dynamiquement.
Auquel je substitue:
scoped_array<Client> cli(new Client [10]);
Donc, du coup on voit que la discipline de programmation en C++ esttrès
éloignée de celle du C; Ce n'était donc pas la peine, lors de la
normalisation, de conserver une "compatibilité à tout prix" avec le C,
puisque, pour écrire "propre" en C++, on n'utilise pratiquement plus
aucun trait de C, au moins pour les tableaux et pointeurs...
On voit donc que la préservation de la compatibilité avec C a eu des
effets plutôt néfastes puisqu'il faut développer, en C++, tout un
ensemble d'outils pour pallier les déficiences du langage C qu'on a
voulu conserver coûte que coûte en C++, pour finalement dire qu'il ne
faut pas les utiliser.
Tout ceci est totalement absurde et rend le langage C++, de loin le
langage le plus abscon de tous les langages de programmation (c'est
quand même le seul langage qui a réussi à inventé des mots clés avec des
underscores !)
Nous sommes d'accord que toute dépendance est source de problème.
C'est bien pour ça que C++0x donne tout un ensemble d'outils pour
rendre la vie plus facile (auto,decltype ...)Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur
un tableau.
Accepté par le compilateur peut être. Ce genre de chose est impossible
à vérifier à la compilation.
Ben si, si on prend la peine d'ajouter des informations sur les
pointeurs...
Je relève quand même dans la norme que :
4.2 Array-to-pointer conversion [conv.array]
1 An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to an rvalue of type
“pointer to T”. The result is a pointer to the first element
of the array. Le chapitre 4 traite des conversions standards
et commence par "Standard conversions are implicit conversions
defined for built-in types". Qu'on le veuille ou non, la
conversion d'un nom de tableau en pointeur sur son premier
élément est bien im-pli-cite et, donc, standard.
Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque
part, dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Oui. Un tableau a un type 'tableau' et un pointeur a un type
'pointeur'. Qu'il y ait une conversion implicite et qu'on puisse
utiliser l'opérateur [] avec un pointeur ne crée pas une identité des
types.
Non pas identité, ce qui n'a jamais été dit, mais équivalence (de par la
conversion implicite justement). Du point de vue de la sémantique
identité et équivalence ne sont pas des termes... équivalents !
[snip]Il y a des décisions apparemment anodines qui coûtent très
cher par la suite quand on normalise.
Les choix de priorités des opérateurs (en particulier les
opérateurs bit à bit) en est un.
Je suis bien d'accord avec toi, mais ça date. (Voir
http://www.quut.com/c/dmr-on-or.html#main pour la question des
priorités, par exemple.) La compatibilité avec C, c'est
probablement la raison principale pour la réussite de C++. C'est
aussi, malheureusement, la source de pas mal de problèmes et
d'ambiguïtés ; je crois qu'on peut dire que le C n'a pas
vraiment été conçu de façon à servir de base de tant de
languages.
C était à l'origine une "commodité" pour éviter que K&R code Unix en
assembleur. Le langage C n'était pas du tout destiné au public (et ça
se voit !). Il aurait dû resté interne aux Bell Labs...
Le C et les autres langages /brackets/ sont aujourd'hui ceux
principalement utilisées dans l'industrie. Pas forcément les plus
adaptés et les plus visuellement plaisant mais l'establishment est là;
ça leur donne quand même une certaine valeur.
Le langage C ne doit sa popularité qu'au succès d'Unix car le couple
C-Unix est l'équivalent (du moins dans le monde système) de l'ancien
couple PL/1-Multics.
J'ai eu l'occasion d'auditer de très nombreux programmes C++.
C'est une des erreurs les plus fréquentes que j'ai rencontrée.
Qu'est-ce qui est l'une des erreurs les plus fréquentes ?
D'utiliser les tableaux de type C quand il existe de meilleurs
alternatifs ?
Non la confusion sur la priorités des opérateurs, dans des
expressions comme :
x & ox00FF + 5 où l'intention du programmeur était de faire
(x & ox00FF) + 5 mais ceci est interprété comme : x & (ox00FF + 5)
car + est plus prioritaire que &, ce qui est une grosse erreur de
conception du langage.
Mais ça permet d'écrire:
if( a < b+1 & a > c ) ...
Et ça aurait peut être causé plus de confusion si ça n'avait pas été
interchangeable avec:
if( a < b+1 && a > c )...
Avoue que l'interchangeabilité de ces deux expressions n'est
certainement pas essentielle en développement.
Ici, on a parlé surtout des confusions occasionnées par les tableaux,
les pointeurs et le mauvais choix de la priorité des opérateurs en
langage C...
Décidément, je n'aime pas du tout le terme "pointer type" qui sème la
confusion.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est la
raison à l'origine de cette décision ?
> C'est bête, mais dans la pratique, je ne me suis jamais servi
> d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
> qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des crochets
pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le tableau
alloué dynamiquement.
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur un
tableau.
> Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands de
tapis".
> Seulement, comment l'améliorer sans briser la comptabilité C. À
> la fin, la décision était de les laisser tels quels, en
> fournissant des altérnatifs nouveaux supérieur (genre
> std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour être
"propre", il faudrait donc transformer toutes les utilisations des tableaux
C en vector lors du passage de C à C++ ou ne jamais utiliser les tableaux C
en C++. Dans ce cas, ça ne servait à rien de conserver la compatibilité...
>> Je relève quand même dans la norme que :
>> 4.2 Array-to-pointer conversion [conv.array]
>> 1 An lvalue or rvalue of type “array of N T” or “array of
>> unknown bound of T” can be converted to an rvalue of type
>> “pointer to T”. The result is a pointer to the first element
>> of the array. Le chapitre 4 traite des conversions standards
>> et commence par "Standard conversions are implicit conversions
>> defined for built-in types". Qu'on le veuille ou non, la
>> conversion d'un nom de tableau en pointeur sur son premier
>> élément est bien im-pli-cite et, donc, standard.
> Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque part,
dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Décidément, je n'aime pas du tout le terme "pointer type" qui sème la
confusion.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est la
raison à l'origine de cette décision ?
> C'est bête, mais dans la pratique, je ne me suis jamais servi
> d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
> qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des crochets
pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le tableau
alloué dynamiquement.
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur un
tableau.
> Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands de
tapis".
> Seulement, comment l'améliorer sans briser la comptabilité C. À
> la fin, la décision était de les laisser tels quels, en
> fournissant des altérnatifs nouveaux supérieur (genre
> std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour être
"propre", il faudrait donc transformer toutes les utilisations des tableaux
C en vector lors du passage de C à C++ ou ne jamais utiliser les tableaux C
en C++. Dans ce cas, ça ne servait à rien de conserver la compatibilité...
>> Je relève quand même dans la norme que :
>> 4.2 Array-to-pointer conversion [conv.array]
>> 1 An lvalue or rvalue of type “array of N T” or “array of
>> unknown bound of T” can be converted to an rvalue of type
>> “pointer to T”. The result is a pointer to the first element
>> of the array. Le chapitre 4 traite des conversions standards
>> et commence par "Standard conversions are implicit conversions
>> defined for built-in types". Qu'on le veuille ou non, la
>> conversion d'un nom de tableau en pointeur sur son premier
>> élément est bien im-pli-cite et, donc, standard.
> Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque part,
dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Décidément, je n'aime pas du tout le terme "pointer type" qui sème la
confusion.
Ce que je ne comprends pas c'est pourquoi la norme l'exige. Quelle est la
raison à l'origine de cette décision ?
> C'est bête, mais dans la pratique, je ne me suis jamais servi
> d'un new [] ni d'un delete []. Qu'un débuttant ne sache même pas
> qu'ils existent ne me gènerait pas outremesure.
C'est bête car je préconise que tout delete soit accompagné des crochets
pour faciliter la maintenance.
En effet :
classe Client {...};
Client* cl = new Client;
plus loin : delete cl;
Un jour on change la déclaration de cl : Client* cl = new Client [10];
delete cl ne détruit pas les instances de Client créées dans le tableau
alloué dynamiquement.
Normalement, delete [] xxx est accepté, même si xxx ne pointe pas sur un
tableau.
> Sauf qu'au départ, il y avait le C. Qui lui évolue de B.
Pour moi, ce n'était pas une raison suffisante. Le processus de
normalisation n'est souvent qu'une série de compromis entre "marchands de
tapis".
> Seulement, comment l'améliorer sans briser la comptabilité C. À
> la fin, la décision était de les laisser tels quels, en
> fournissant des altérnatifs nouveaux supérieur (genre
> std::vector).
D'accord, cette décision n'a pas brisé la compatibilité, mais pour être
"propre", il faudrait donc transformer toutes les utilisations des tableaux
C en vector lors du passage de C à C++ ou ne jamais utiliser les tableaux C
en C++. Dans ce cas, ça ne servait à rien de conserver la compatibilité...
>> Je relève quand même dans la norme que :
>> 4.2 Array-to-pointer conversion [conv.array]
>> 1 An lvalue or rvalue of type “array of N T” or “array of
>> unknown bound of T” can be converted to an rvalue of type
>> “pointer to T”. The result is a pointer to the first element
>> of the array. Le chapitre 4 traite des conversions standards
>> et commence par "Standard conversions are implicit conversions
>> defined for built-in types". Qu'on le veuille ou non, la
>> conversion d'un nom de tableau en pointeur sur son premier
>> élément est bien im-pli-cite et, donc, standard.
> Certes. Qui a dit le contraire ?
La formulation de Jean-Marc Bourguet peut le laisser croire, quelque part,
dans ce fil, je cite : "faire croire que le nom d'un
tableau a un type pointeur ne fait qu'augmenter la confusion -- en
particulier en C++."
Ce qui pose la question des VLAs pour C++0x. Je comprends que ça puisse
rendre la vie de compilateurs plus difficile mais c'est AMA là où il y a le
plus de travail quand on porte du code C99 vers C++ (ou quand le code à été
écrit sur un compilateur souple).
Ce qui pose la question des VLAs pour C++0x. Je comprends que ça puisse
rendre la vie de compilateurs plus difficile mais c'est AMA là où il y a le
plus de travail quand on porte du code C99 vers C++ (ou quand le code à été
écrit sur un compilateur souple).
Ce qui pose la question des VLAs pour C++0x. Je comprends que ça puisse
rendre la vie de compilateurs plus difficile mais c'est AMA là où il y a le
plus de travail quand on porte du code C99 vers C++ (ou quand le code à été
écrit sur un compilateur souple).