Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[debutant] tableaux dynamiques et pointeurs

14 réponses
Avatar
Rincevent06
Bonjour, je ne suis pas sur de bien comprendre le fonctionnement des
tableaux dynamiques...
Quelqu'un peut-il me dire si mes définitions sont exactes ? (pour faciliter
la lecture, mes questions sont précedées du symbole #)

1)
# L'interet d'un tableau dynamique par rapport à un tableau statique est
qu'on peut liberer la mémoire utilisée par le tableau lorsqu'on a finit de
l'utiliser ?
# Ca apporte juste l'avantage de pouvoir "gerer" la mémoire ?
# Y-a-t-il d'autres avantages ?

2) Dans mon cours, nous avons détaillé trois étapes fondamentales : la
déclaration, l'allocation mémoire et la désallocation mémoire. Voici ce que
j'ai compris des 2 premières étapes:

--> La déclaration :
int *tab = NULL;

# Ici on "réserve" un emplacement mémoire pour un tableau contenant des
entiers (int). Ses valeurs sont stockées dans *tab (par exemple (*tab)[0]
renverrais le 1er élement si on l'avait définit). Son adresse est stockée
dans tab.

# Ici ce qu'on affecte à la valeur NULL, c'est bien le tableau en lui même ?
# A cette étape, que vaut tab ?

--> L'allocation mémoire :
tab = new int[taille];

Ici je n'ai pas très bien compris.
# Apparemment, on change la valeur de tab qui est l'adresse du tableau *tab
?
# On lui applique une nouvelle adresse à l'aide de la commande new ?
# Mais alors, où était stocké le tableau avant cette procédure ???

# En clair, les 2 lignes suivantes effectuent la même opération : renvoyer
l'adresse où est stockée la valeur de l'entier 55, c'est bien ça ?

int *n=55;
cout << n;

int n=55;
cout << &n;

si on tape :
int n=55;
# Quel est le type de &n ? Une chaîne de caractère ?
# Si on voulait l'attribuer à une variable x (qui contiendrait donc
l'adresse de n). Une façon possible serait :

int *x = NULL; (1)
x=&n; (2)

(1) : *x est un entier, il a la valeur NULL (cad 0 ?), son adresse est
quelconque...

(2) : on change l'adresse x de *x, sa nouvelle adresse est celle de n.
Auquel cas, la variable x contient l'adresse de n.
*x a également changé, il contient désormais la valeur de n ?
Si on change la valeur de n, celle de *x change aussi non ?
Réciproquement, si on change la valeur de *x (est-ce possible ?),
qu'advient-t-il d ela valeur de n ?


Enfin, ma dernière question :
Dans une procédure qui utilise un tableau T comme argument, une définition
possible est :

void ma_fonction ( int T[ ] )

(dans le cas où la fonction renvoie void et où le tableau contient des
entiers).

Or le prof nous a donné une autre définition qui focntionne aussi et qui
est, selon lui, "plus générale" :

void ma_fonction ( int *T )

# Y-a-t-il un lien entre cette écriture et l'opérateur * (*x = valeur
contenue à l'adresse x) ?

Merci à ceux qui ont eu le courage de lire mon (long) message jusqu'au bout
;-)
Si vous pouviez répondre à mes questions, je vous en suis reconnaissant.
N'ayant que mon cours "papier" sur moi, je ne suis pas en mesure de tester
toutes mes suppositions sur un compilateur :-(

Merci encore

RCV

4 réponses

1 2
Avatar
Pierre Maurette
"Loïc Joly" a écrit ...
Pierre Maurette wrote:

Déjà commenté l'aspect autonome, à mon sens, du C++.
Un prof qui insiste lourdement sur les pointeurs avant de passer à la
suite,


ça ne me paraît pas si mal.


Je nuancerais en disant que si ce point du cours vien au bon moment
(c'est à dire l'apprentissage des pointeurs et des allocations de
tableau à la C APRES l'apprentissage de l'utilisation de std::vector),
alors ça ne me gêne aucunement et ça fait partie de ce que quelqu'un qui
progremme en C++ DOIT savoir, même s'il ne l'utilisera pas souvent.
Vous êtes certainement dans le vrai. Disons que je ne raisonne pas

uniquement en fonction d'un public de futurs informaticiens, par exemple des
électroniciens. Dans ce cas, une approche "historique", le C (amélioré) dans
le C++, puis les classes (en gros), permet d'aborder les deux langages pour
pas plus cher. De plus, dans le cadre malheureusement trop fréquent du "on
fait au mieux avec le temps qu'on nous donne", et en fonction de ce public,
je préfèrerais assurer les bases "non objet" du langage. Mais je ne suis pas
enseignant.
J'imagine sans peine que ce n'est pas la meilleure méthode pour faire de
bons programmeurs C++.

Pierre


Avatar
Pierre Maurette
"James Kanze" a écrit ...
"Pierre Maurette" <mmaauurreettttttee.ppiieerrrree@@ffrreeee.ffrr> writes:

|> "Martinez Jerome" a écrit
...


|> > > 2) Dans mon cours, nous avons détaillé trois étapes
|> > > fondamentales : la déclaration, l'allocation mémoire et la
|> > > désallocation mémoire. Voici ce que j'ai compris des 2
|> > > premières étapes:
[...]

|> En fait, si le cycle déclaration/allocation/désallocation, et
|> la différence entre déclarer un pointeur et déclarer un
|> tableau de taille fixe, n'est pas claire, il est inutile de
|> continuer.

Quel rapport entre la taille des tableaux, le cycle
allocation/désallocation (parce qu'il n'y a pas normalement un cylce
déclaration/allocation/désallocation), et les pointeurs ?
Le rapport, c'est que c'est la question initiale du fil ;-). (Et puis, les

fonctions ou opérateurs d'allocation renvoient un pointeur. Le rapport
existe, et vous-même ne l'ignorez pas).
Question initiale à laquelle j'ai commencé par tenter d'apporter une
réponse, "à la C" j'en conviens, c'est à dire dans l'esprit de la question.
M. Rincevent (c'est joli, Rincevent, ça sonne comme un petit coup de blanc
sec de la Loire) nous pose une question. Il bosse sur un poly, sans accès à
un compilateur, ce qui est peut-être un bien après tout. Je me refuse à le
renvoyer dans ses 22 en lui disant "c'est pas du VRAI C++", et surtout de le
faire douter en critiquant son prof. Ce prof a peut-être fait le choix
d'appeler C++ un cours de premier langage, ou de langage unique. Nous
ignorons de quel cursus il s'agit, ni quel rôle y joue l'informatique.


|> Et personnellement je n'aurais pas d'état d'âme à utiliser
|> malloc() et free(), fonctions définies dans la norme C++, à ce
|> niveau de l'apprentissage.

Pour donner aux élèves de mauvaises habitudes, et des sources
d'erreurs supplémentaires ?
Parce que dans le cadre d'un cours C++ premier langage, il faut aborder

l'aspect C du C++, qui figure dans la norme C++. Je comprends vos critiques,
et votre désir d'une "pureté" du C++. Néanmoins, vous comme moi, nous
CONNAISSONS plus ou moins le C et ses spécificités. Avons-nous alors les
moyens de savoir s'il est possible pour un débutant de l'ignorer, qu'on
l'appelle "C" ou "à la C" ? Je ne vois pas M. Rincevent continuer
sereinement sa route vers les classes, les méthodes virtuelles, les
templates, et que sais-je encore, avec la représentation qu'il se fait
aujourd'hui d'un pointeur et de l'allocation mémoire. Il aurait fallu alors
les ignorer. Pourquoi pas ? Pourquoi ne pas alors enseigner Java ? Je ne
plaisante pas, il me semble que cette voie est ou a été choisie aux
Etats-Unis.


|> Il me semble que souvent, les gars sortent encore vaseux des
|> pointeurs, pour attaquer bille en tête les références, au
|> plus mauvais moment pour aborder cette notion (je vois un meilleur
|> endroit, avec les fonctions, personnellement).

Je dirais effectivement que les fonctions et les références
doivent être enseignées bien avant les pointeurs. (Je suis
peut-être un peu hérétique, mais je crois que les fonctions
seraient le premier contrôle de flux d'execution que j'enseignerais.
Avant des boucles et des conditionnels, par exemple.)
Oui, les fonctions sont centrales, puisque tout code est dans une fonction.

D'où bloc, d'où visibilité et durée de vie.
Je ne vois même pas l'ébauche d'un plan linéaire, sans référence forward à
chaque paragraphe, d'enseignement du C++ à partir de rien. Que faire dans
une fonction sans variable ? J'imagine un dégrossissage rapide (K&R
commençait par "Hello, world !", je C, CT du C), suivi d'une série de thèmes
en niveau 1, puis des mêmes et/ou d'autres en niveau 2 (niveau 1 et niveau 2
ne correspondent à rien de précis).
Je suis dans une optique "apprendre les bases avant les classes", il y a
bien en partie l'idée (seulement l'idée) le C puis le C++, je comprends et
admets vos critiques à ce sujet.
L'introduction des références avec les fonctions semble efficace. Déjà,
parce qu'on éloigne les notions de pointeur et de référence. Bien entendu,
il ne faut pas avoir commencé par déconner, en parlant de "passage par
valeur" et "passage par pointeur". Hors les références, une fonction ne sait
transmettre que des valeurs. Que ce soit la valeur d'un pointeur ne change
rien à l'affaire.
J'aime bien l'idée de proposer, avant les références, UN mécanisme de
passage de paramètre (sur UNE implémentation), parler de choses aussi peu
portables que la pile, voire de façon simplifiée les cadres de piles. Il est
difficile d'éluder les conventions d'appel.
Pour bien montrer ensuite qu'avec le passage par référence, on change de
dimension, et on prépare ainsi à un niveau d'abstraction nécessaire pour la
suite. J'aime bien voir la référence comme un élément du dialogue entre le
programmeur et le compilateur. Que celui-ci peut le résoudre par un pointeur
ou non n'a pas d'importance.

|> > Relis ton cours de C, et reecris correctement ta ligne de code :

|> Pourquoi aurait-il un cours de C ? Le C++ est un langage autonome.

|> > int* tab=NULL;
|> > et non
|> > int *tab=NULL,
|> > tab est de type int*.

|> C'est mon choix également, comme dirait notre Marianne.
|> Qui plus est dans une approche pédagogique.

Qu'est-ce qu'il y a de pédagogique à montrer quelque chose dont on
ne se sert jamais ?
Je trouve plus facile d'écrire :

int* tab = NULL;
et de dire que tab est déclaré en tant que int* et initialisé à NULL.
Pour ce qui est de l'inutilité d'enseigner le pointeur, accepteriez-vous
vous-même de l'ignorer ?

Cordialement,
Pierre

Avatar
James Kanze
"Pierre Maurette" <mmaauurreettttttee.ppiieerrrree@@ffrreeee.ffrr> writes:

|> "James Kanze" a écrit ...
|> > "Pierre Maurette" <mmaauurreettttttee.ppiieerrrree@@ffrreeee.ffrr>
|> > writes:
|> > |> "Martinez Jerome"
|> > |> a écrit
|> ...
|> >
|> > |> > > 2) Dans mon cours, nous avons détaillé trois étapes
|> > |> > > fondamentales : la déclaration, l'allocation mémoire et la
|> > |> > > désallocation mémoire. Voici ce que j'ai compris des 2
|> > |> > > premières étapes:
|> [...]
|> > |> En fait, si le cycle déclaration/allocation/désallocation, et
|> > |> la différence entre déclarer un pointeur et déclarer un
|> > |> tableau de taille fixe, n'est pas claire, il est inutile de
|> > |> continuer.
|> > Quel rapport entre la taille des tableaux, le cycle
|> > allocation/désallocation (parce qu'il n'y a pas normalement un
|> > cylce déclaration/allocation/désallocation), et les
|> > pointeurs ?

|> Le rapport, c'est que c'est la question initiale du fil ;-). (Et
|> puis, les fonctions ou opérateurs d'allocation renvoient un
|> pointeur. Le rapport existe, et vous-même ne l'ignorez pas).

En C++ bien écrit, un tableau dynamique serait toujours un type de
classe. Même avant la STL.

En C, il y a une série de points à aborder, mais la taille d'un
tableau reste toujours assez indépendante de son
allocation/désallocation (ce qui est en fait un des problèmes avec
les tableaux C -- la taille n'en fait pas partie).

|> Question initiale à laquelle j'ai commencé par tenter
|> d'apporter une réponse, "à la C" j'en conviens, c'est à
|> dire dans l'esprit de la question. M. Rincevent (c'est joli,
|> Rincevent, ça sonne comme un petit coup de blanc sec de la Loire)
|> nous pose une question. Il bosse sur un poly, sans accès à un
|> compilateur, ce qui est peut-être un bien après tout. Je me
|> refuse à le renvoyer dans ses 22 en lui disant "c'est pas du VRAI
|> C++", et surtout de le faire douter en critiquant son prof.

Je suis d'accord que dire simplement que ce n'est pas du C++, ce n'est
pas bien. Montrer comment on fait en C++ (c-à-d std::vector), en
revanche, je trouve plutôt bien. Parce que c'est comme ça qu'on
fait en C++.

Maintenant, comme tu dis, il peut y avoir des raisons pour que le prof
présente le C. Mais dans ce cas-là, il faudrait aussi montrer
malloc et free. Et pour la discussion, c'est plutôt fr.comp.lang.c
qui convient.

Et si le prof essaie à présenter les deux langages en les
mélangeant, il faut le critiquer. Ce sont deux langages distincts, et
même s'il y a un sous-ensemble commun, les solutions idiomatiques
dans un ne le sont pas dans l'autre.

|> Ce prof a peut-être fait le choix d'appeler C++ un cours de
|> premier langage, ou de langage unique. Nous ignorons de quel cursus
|> il s'agit, ni quel rôle y joue l'informatique.

Certes, mais il y a C, et il y a C++. On peut vouloir en enseigner les
deux, mais même alors, il faut bien les tenir separer.

|> > |> Et personnellement je n'aurais pas d'état d'âme à
|> > |> utiliser malloc() et free(), fonctions définies dans la
|> > |> norme C++, à ce niveau de l'apprentissage.

|> > Pour donner aux élèves de mauvaises habitudes, et des
|> > sources d'erreurs supplémentaires ?

|> Parce que dans le cadre d'un cours C++ premier langage, il faut
|> aborder l'aspect C du C++, qui figure dans la norme C++.

Là, je ne suis pas du tout d'accord. Que dans certains contextes, on
voudrait aussi présenter le C, peut-être, bien que je suis
sceptique -- on enseigne ou bien le C ou bien le C++, mais il faut bien
les distinguer. Et dans un premier cours C++, on n'aborde réelement
que ce qui est du C++ idiomatique.

|> Je comprends vos critiques, et votre désir d'une "pureté" du
|> C++. Néanmoins, vous comme moi, nous CONNAISSONS plus ou moins le
|> C et ses spécificités. Avons-nous alors les moyens de savoir
|> s'il est possible pour un débutant de l'ignorer, qu'on l'appelle
|> "C" ou "à la C" ?

As-tu vu des textes récents d'enseignement du C++, comme le Koenig et
Moo ? Si l'élève ne connaît pas encore du C, je ne vois pas de
raison de lui en parler. Sauf, éventuellement, pour des interfaces
avec des API C.

|> Je ne vois pas M. Rincevent continuer sereinement sa route vers les
|> classes, les méthodes virtuelles, les templates, et que sais-je
|> encore, avec la représentation qu'il se fait aujourd'hui d'un
|> pointeur et de l'allocation mémoire. Il aurait fallu alors les
|> ignorer. Pourquoi pas ? Pourquoi ne pas alors enseigner Java ? Je ne
|> plaisante pas, il me semble que cette voie est ou a été
|> choisie aux Etats-Unis.

À vrai dire, je dirais que ni le Java, ni le C++ ne convient comme
premier langage. Dans le deux cas, il y a trop de « magique » et
trop de pièges qu'il faut présenter avant même le premier
programme. (C'est quoi, une fonction ? Ou sinon, main lui-même est
une incantation magique.)

Si on fait le choix de C++ ou de Java, alors, c'est pour des raisons
pratiques ; c'est le langage qu'il risque d'utiliser par la suite, dans
la vie professionnelle. Et si on choisit le C++, il faut donc lui
montrer le C++, tel qu'on s'en sert dans la vie professionnelle. Ou
plutôt, tel qu'on s'en servira une fois qu'il a fini l'école --
aujourd'hui, il y a encore pas mal de projets C++ qui n'utilisent pas la
STL, pour une raison ou une autre. Mais demain ? (Et de toute façon,
ceux qui n'utilisent pas la STL utilise quelque chose d'autre -- comme
j'ai dit par ailleurs, en plus de dix ans d'expérience en C++, je
n'ai jamais vu un new[].)

|> > |> Il me semble que souvent, les gars sortent encore vaseux des
|> > |> pointeurs, pour attaquer bille en tête les
|> > |> références, au plus mauvais moment pour aborder cette
|> > |> notion (je vois un meilleur endroit, avec les fonctions,
|> > |> personnellement).

|> > Je dirais effectivement que les fonctions et les références
|> > doivent être enseignées bien avant les pointeurs. (Je suis
|> > peut-être un peu hérétique, mais je crois que les
|> > fonctions seraient le premier contrôle de flux d'execution que
|> > j'enseignerais. Avant des boucles et des conditionnels, par
|> > exemple.)

|> Oui, les fonctions sont centrales, puisque tout code est dans une
|> fonction. D'où bloc, d'où visibilité et durée de vie.

|> Je ne vois même pas l'ébauche d'un plan linéaire, sans
|> référence forward à chaque paragraphe, d'enseignement du
|> C++ à partir de rien. Que faire dans une fonction sans variable ?
|> J'imagine un dégrossissage rapide (K&R commençait par "Hello,
|> world !", je C, CT du C), suivi d'une série de thèmes en
|> niveau 1, puis des mêmes et/ou d'autres en niveau 2 (niveau 1 et
|> niveau 2 ne correspondent à rien de précis).

|> Je suis dans une optique "apprendre les bases avant les classes", il
|> y a bien en partie l'idée (seulement l'idée) le C puis le C++,
|> je comprends et admets vos critiques à ce sujet.

J'avoue que j'introduirais les classes (et l'encapsulation) assez tôt
dans l'enseignement. Mais ici, ce n'est pas la question. La question
concerne les tableaux, et on n'a pas besoin de connaître les classes
pour apprendre que la façon qu'on déclare un tableau (dynamique ou
autre) en C++, c'est std::vector<int> tableau.

|> L'introduction des références avec les fonctions semble
|> efficace. Déjà, parce qu'on éloigne les notions de pointeur
|> et de référence. Bien entendu, il ne faut pas avoir
|> commencé par déconner, en parlant de "passage par valeur" et
|> "passage par pointeur". Hors les références, une fonction ne
|> sait transmettre que des valeurs. Que ce soit la valeur d'un
|> pointeur ne change rien à l'affaire.

Mais vue que j'aurais présenté les fonctions et les
références bien avant de présenter les pointeurs...

|> J'aime bien l'idée de proposer, avant les références, UN
|> mécanisme de passage de paramètre (sur UNE implémentation),
|> parler de choses aussi peu portables que la pile, voire de façon
|> simplifiée les cadres de piles. Il est difficile d'éluder les
|> conventions d'appel.

Je ne sais pas. Ça n'a jamais posé des problèmes quand on
enseignait du Pascal. Quand j'ai enseigné du C, je me servait de
«@Programming Tools in Pascal » (de Kernighan et Plauger) comme
texte de base. Évidemment, parce qu'il s'agissait de C, j'ai dû
introduire des pointeurs pour les paramètres de type VAR. Mais dans
un premier temps, uniquement pour ça. Et ce n'était que vraiment
vers la fin que j'introduisais l'utilisation des pointeurs pour des
tableaux dynamiques.

En C++, le problème est plus simple. Parce qu'on a std::vector, mais
aussi parce que quelque chose comme :
void f( T (&tableau)[] ) ;
est légal en C++.

En fait, en dehors de l'implémentation des classes de tableau, je ne
crois que je ne me sers jamais des T* vers des tableaux. Et
l'implémentation d'une classe de tableau, ce n'est pas quelque chose
que je présenterais dans une classe de débutants.

|> Pour bien montrer ensuite qu'avec le passage par référence, on
|> change de dimension, et on prépare ainsi à un niveau
|> d'abstraction nécessaire pour la suite. J'aime bien voir la
|> référence comme un élément du dialogue entre le
|> programmeur et le compilateur. Que celui-ci peut le résoudre par
|> un pointeur ou non n'a pas d'importance.

Tout à fait. En fait, on l'enseigne bien avant d'enseigner les
pointeurs.

|> > |> > Relis ton cours de C, et reecris correctement ta ligne de
|> > |> > code :

|> > |> Pourquoi aurait-il un cours de C ? Le C++ est un langage
|> > |> autonome.

|> > |> > int* tab=NULL;
|> > |> > et non
|> > |> > int *tab=NULL,
|> > |> > tab est de type int*.

|> > |> C'est mon choix également, comme dirait notre Marianne. Qui
|> > |> plus est dans une approche pédagogique.

|> > Qu'est-ce qu'il y a de pédagogique à montrer quelque chose
|> > dont on ne se sert jamais ?

|> Je trouve plus facile d'écrire :
|> int* tab = NULL;
|> et de dire que tab est déclaré en tant que int* et
|> initialisé à NULL. Pour ce qui est de l'inutilité
|> d'enseigner le pointeur, accepteriez-vous vous-même de
|> l'ignorer@?

Je vois bien l'utilité des pointeurs. On ne peut pas faire des
structures dynamiques (arborescences, listes, etc.) sans les pointeurs.
Je les présenterais donc quand on aborde ces structures.

Mais je répète, en C++, un pointeur n'a rien avoir avec un tableau
dynamique, et on ne s'en sert pas pour des tableaux dynamiques. Dans un
premier cours, je crois que je dirais simplement qu'on n'alloue pas des
tableaux de type C dynamiquement, sans entrer plus dans les détails.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
Pierre Maurette
"James Kanze" a écrit ...
[Long mais tellement bon ...]
Mais je répète, en C++, un pointeur n'a rien avoir avec un tableau
dynamique, et on ne s'en sert pas pour des tableaux dynamiques. Dans un
premier cours, je crois que je dirais simplement qu'on n'alloue pas des
tableaux de type C dynamiquement, sans entrer plus dans les détails.
Je vous remercie pour vos avis, dont je ne manque jamais de tenir compte.

Bien que je sois un peu têtu, isn't it.
Je viens de poser une question sur les pointeurs de fonctions, je compte
beaucoup sur votre avis, vous pouvez même me renvoyer sur fclc, du moment
que vous me donnez votre réponse ;-)
Cordialement,
Pierre

1 2