OVH Cloud OVH Cloud

Definition d'un "nom de tableau"

81 réponses
Avatar
candide
Ce que je fais là est un peu cavalier mais j'ouvre un fil pour répondre
au message de François, l'autre fil devenant vraiment trop anarchique.

Francois a écrit :

>
> « Le nom t d'un tableau est une *constante* de type pointeur dont la
> valeur est fixée une bonne fois pour toute au début de l'exécution du
> programme et n'est pas stockée en mémoire. »
>
> est-ce correct ? J'ai l'impression que oui bien sûr, mais je me trompe
> peut-être (sûrement).


Je ne comprends pas ton obstination à vouloir trouver une définition
parfaite de "nom d'un tableau", ce qui compte aussi c'est de savoir les
utiliser ces tableaux mais peut-être que tu ne pourras faire cela
qu'après avoir défini, ce en quoi on reconnait le matheux ;) .

Et maintenant tu compliques les choses en parlant non plus de tableau
mais de nom d'un tableau.


À mon avis, ta définition est totalement incorrecte même si je
vois bien l'idée.

"Un nom de variable est une constante" ? Bof, dans la
norme (que je la connais très mal, OK), les constantes et les noms de
variables (les identificateurs) ne sont pas dans la même catégorie de
"token" donc on ne peut pas dire formellement qu'un identificateur est
une constante.

"Un tableau est de type pointeur", c'est une horreur, un tableau est de
type tableau, c'est tout même si une expression de type tableau est,
dans certaines circonstances, convertie en pointeur.

La valeur de t est fixée une bonne fois pour toutes au début ? oui, me
semble-t-il et encore, je sens que certains vont chipoter.


"La valeur n'est pas stockée en mémoire" : à mon avis, non, un tableau
est un objet, comment on y accèderait sinon ?

Comme dit la faq de clc à propos de l'expression "un tableau est un
pointeur constant" (question 6.9) : un nom de tableau est constant dans
la mesure où on ne peut l'assigner mais une fois de plus, un tableau
n'est pas un pointeur.

10 réponses

Avatar
candide
-------------------------
§5.4.2
Multidimensional arrays are declared "arrays of arrays", such as in
the declaration

int matrix[12][10];

wich declares to be a 12-by-10 element array of int.
-------------------------


concorde parfaitement avec :

--------------------8<----------------------------------------
6.5.2.1 Array subscripting
4 EXAMPLE Consider the array object defined by the declaration
int x[3][5];
Here x is a 3 ´ 5 array of ints; more precisely, x is an array of
three element objects, each of which is an array of five ints.
-------------------->8----------------------------------------




Non, ce qui change _tout_ pour celui qui recherche l'information, c'est
ce qui suit le "more precisely," dans la norme.


Par ailleurs, la suite de ton message est d'un ton que je trouve
inapproprié, peut-être était-il trop tôt ou trop tard quand tu as écrit
ton message.


Toujours en train de vous crisper comme des dingues ?


Ton message contient des informations qui ne sont pas univoques :
ton "vous" est-il singulier ou pluriel ? pourquoi parles-tu de
"dingues" et tu ne cites qu'une personne (moi en l'occurrence) ? quels
sont les dingues (autres que moi) ?


Vous n'avez
pas lu la faq dont je donnais le lien tantôt alors...



"tantôt" ? tu peux pas t'exprimer précisément, usuellement "tantôt" veut
dire dans un délai, postérieur ou antérieur, de l'ordre de la
demi-journée (ou la journée selon le Robert). Or je ne vois aucun
message de ta part dans un tel délai. Tu as bien posté un lien vers une
FAQ mais c'était précisément il y a 10 jours, donc "tantôt" ...

Par ailleurs, je viens à nouveau de regarder cette FAQ, elle est
totalement indigente et ne mérite même pas d'être cité, ça fait partie
du bruit documentaire qui rend la compréhension du C plus difficile.

Tu pourrais au minimum citer la FAQ de fclc (que j'ai trouvée illisible
même avec plusieurs mois de C) ou de clc (moins illisible, plus
substancielle et mieux organisée mais c'est pas encore ça et tant s'en
faut). J'ai regardé chacune de ces faq pour cette histoire de tableaux
multidimensionnels et aucune ne répond à la question précise de François
(sauf lecture trop rapide de ma part). Bref, l'inadéquation habituelle.


En rapport avec l'inadéquation du contenu de ton message, je n'ose pas
imaginer la qualité d'une documentation sur le C écrite par toi.


Avatar
candide

Effectivement, on comprend bien alors qu'un tableau dit
"multidimensionnel" n'est en réalité qu'un tableau à une seule dimension
dont le nombre d'éléments est donné par le premier "chiffre" entre



"chiffre" : curieux que tu emploies ce terme.




Est-ce que c'est correct ou je délire ?

Moi je trouve que c'est correct. Personnellement j'utilise

préférentiellement t[i][j] aux notations utilisant l'opérateur *.


Par ailleurs, concernant les tableaux (uni ou pluri-dimensionnels), la
nécessité quand on les découvre, c'est moins de savoir les définir que
de savoir les utiliser (point de vue personnel).


Puisque tu es à la recherche de documentation sur les tableaux, je me
rappelle avoir trouvé assez intéressantes les explications de faq de
clc, section 6.

Avatar
Marc Boyer
On 2008-03-19, candide wrote:

N'ais-je pas convaincu que les gens qui savaient déjà ?

Rassure-moi, on peut quand même faire honnêtement du C sans savoir

comment marche un compilateur, y compris l'ignorer dans les grandes
lignes ?


Je ne sais pas.

Je pense qu'on ne peut pas s'affranchir de certains points
d'organisation mémoire, et que certaines connaissances sur
les pb d'alignement permettent de "mieux" intégrer les
restrictions imposées par la norme.

Il y a aussi les pb préprocesseur/compilateur/éditeur
de lien, qui peuvent donner des bugs difficiles à comprendre,
si on a pas quelques notions. Bien sur, si on suit à
la lettre la norme, on ne fait pas ses erreurs. Mais un
fois l'erreur faite, il faut comprendre le message du
compilo/editeur de lien, voir le bug...

Après, mes étudiants suivent quelques cours d'archi des
ordis + assembleurs avant de faire du C, mais rien sur
le fonctionnement des compilateurs en détail. Parfois
quelques remarques faites à l'oral sur le compilo,
mais pas grand chose.

Au final, ils s'en sortent.

Donc, je pense qu'il faut avoir quelques connaissances
sur le fonctionnement du compilo et du processeur. Quantifier
le "quelques" est assez difficile.

Faut pas oublier que C a été inventé à une époque ou
tous les programmeurs faisaient quotidiennement de
l'assembleur.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)


Avatar
Marc Boyer
On 2008-03-19, Francois wrote:
Merci beaucoup ! C'est donc bien ce que je pensais. Cela peut paraître
anodin comme question, mais en fait je trouve que ça ne l'est pas. Par
exemple, après

int tab[3][4] ;

les occurrences futures de tab seront en général (d'après la *règle* qui
admet 3 exceptions) converties en la valeur d'un pointeur sur un tableau
de 4 entiers


Oui.

et tab+1 aussi (il donnera l'adresse du deuxième élément du
tableau tab [qui est un tableau à 4 quatre éléments de type entier]).
Donc, comprendre le type permet de bien comprendre le "+1" dans "tab+1".


En effet.

On a
(void*) (tab+1) == (void*) &(tab[1]) == (void*) &(tab[1][0])

Effectivement, on comprend bien alors qu'un tableau dit
"multidimensionnel" n'est en réalité qu'un tableau à une seule dimension
dont le nombre d'éléments est donné par le premier "chiffre" entre
crochet et dont chaque élément sera un tableau (dont les éléments
pourront être éventuellement des tableaux eux aussi, ainsi de suite ...).


Exactement.
D'ailleurs, dans mon cours, la première phrase que je dis sur
les tableaux à plusieurs dim, c'est que ce sont des tableaux de
tableaux.

Je crois que je commence à comprendre alors les explications de
Jean-Marc Bourget et sa vision systématique des tableaux. Je tente une
explication. Surtout, rectifiez moi si je dis des bêtises !

Supposons que l'on ait int tab[3][4] ;

L'objet tab est un tableau à 3 éléments que je vais énumérer
symboliquement par tab0, tab1 et tab2 qui sont chacun des tableaux de
quatre entiers.


Oui.
D'ailleurs
sizeof( tab[0] ) == 4 * sizeof(int)


Supposons qu'on ait à un moment donné tab[1][3] ;

Effectivement, tab est alors converti en une valeur de type pointeur sur
son premier élément. Donc tab est converti en une valeur égale à
l'adresse de tab0 (l'adresse du premier byte de tab0) vue avec le type
de tab0, c'est-à-dire le type tableau de quatre entiers.

tab[1][3] est alors pour moi converti en *(*(tab+1)+3)


Tout à fait. Mais c'est pénible à lire et écrire.

*(tab+1) est le deuxième élément de tab, c'est-à-dire tab1. Donc en fait
on a :

tab[1][3] converti en *(*(tab+1)+3) équivalent à *(tab1+3)

Or, tab1 est un tableau de 4 entiers. Dans ce contexte, il est lui aussi
converti à son tour en une valeur de type pointeur vers son premier
élément. Une fois tab1 converti, *(tab1+3) donne enfin le quatrième
élément (un entier) de tab1. Donc, tout ça pour dire que tab[1][3] est
le quatrième élément de tab1 !


Il me semble oui (je suis pas super réveillé, j'ai peut-etre raté
un truc).

Conclusion, si j'ai bien compris : l'opération i[j] en C est converti en
des *(i+j) et c'est une simple commodité d'écriture. Mais vu mon
raisonnement précédent, cette commodité est une chose bien pratique pour
la lisibilité.



Oui.
D'ailleurs, pour l'anecdote, tu peux écrires
tab[i] ou i[tab], c'est pareil pour le compilo (mais pas
forcément pour le lecteur).

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)

Avatar
espie
In article <47e06074$0$29138$,
candide wrote:

N'ais-je pas convaincu que les gens qui savaient déjà ?

Rassure-moi, on peut quand même faire honnêtement du C sans savoir

comment marche un compilateur, y compris l'ignorer dans les grandes
lignes ?


Tu connais le mythe de la caverne ?

C'est parfaitement applicable a la personne qui essaiera de comprendre
les points de detail du langage sans savoir comment fonctionne un
compilateur...


Avatar
YBM
"tantôt" ? tu peux pas t'exprimer précisément, usuellement "tantôt" veut
dire dans un délai, postérieur ou antérieur, de l'ordre de la
demi-journée (ou la journée selon le Robert). Or je ne vois aucun
message de ta part dans un tel délai. Tu as bien posté un lien vers une
FAQ mais c'était précisément il y a 10 jours, donc "tantôt" ...


10 jours, c'est une journée à l'échelle de l'histoire du C...

Par ailleurs, je viens à nouveau de regarder cette FAQ, elle est
totalement indigente et ne mérite même pas d'être cité, ça fait partie
du bruit documentaire qui rend la compréhension du C plus difficile.


Tsss tsss... tu ne l'as vraiment pas lue...

En rapport avec l'inadéquation du contenu de ton message, je n'ose pas
imaginer la qualité d'une documentation sur le C écrite par toi.


... vraiment pas lue. Où peut-être que le concept principal de cette FAQ
t'es parfaitement étranger, il y a des gens comme ça...

Avatar
candide

Tsss tsss... tu ne l'as vraiment pas lue...


Effectivement


En rapport avec l'inadéquation du contenu de ton message, je n'ose pas
imaginer la qualité d'une documentation sur le C écrite par toi.


... vraiment pas lue. Où peut-être que le concept principal de cette FAQ


Vous avez dit "concept" ?

t'es parfaitement étranger,


Non. Mais "the shorter the better".


Avatar
Jean-Marc Bourguet
Francois writes:

Lorsqu'on déclare un " int tab2[10][12]; " alors tab2 est bien une variable
de type tableau de 10 éléments de type tableau de 12 entiers, et non
l'inverse (à savoir variable de type tableau de 12 éléments de type tableau
de 10 entiers). Est-ce correct ?


Oui.

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Jean-Marc Bourguet
candide writes:


N'ais-je pas convaincu que les gens qui savaient déjà ?


Rassure-moi, on peut quand même faire honnêtement du C sans savoir comment
marche un compilateur, y compris l'ignorer dans les grandes lignes ?


Oui. Mais alors il faut abandonner l'idee de comprendre le pourquoi des
regles. Et tu auras beaucoup plus de mal a les apprendre.

Si tu veux faire cet exercice, je te conseille d'apprendre un autre langage
que le C. Des langages comme Lisp, ML ou Haskell conviendraient beaucoup
mieux a ce genre d'exercice.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Francois
Merci beaucoup pour vos confirmations. Le concept "tableau" est
maintenant beaucoup plus clair. Le cours de Bernard Cassagne explique
pas mal du tout cela, je trouve.

Effectivement, il dit bien que tab[i] et i[tab] sont rigoureusement
identiques (quelle horreur !) ce qui est logique.

Concernant le décorticage de "tab[1][3] ;", ça rend un peu les choses un
peu illisible de passer par les pointeurs et c'est sans doute plus
rapide de se dire que simplement que :

- tab[1] est le deuxième élément de tab (qui est un tableau lui-même)
- donc tab[1][3] est le quatrième élément du tableau tab[1]

Mais, c'est bien de comprendre le décorticage aussi, car on comprend
mieux par exemples les définitions de fonctions qui prennent un pointeur
en argument et qui peuvent prendre en fait un tableau en argument grâce
à la conversion.


J'ai encore une question sur les tableaux que je me posais. Comment
déclare-t-on un tableau de 10 pointeurs sur entiers par exemple ?

Je pensais au départ à int (*p)[10], mais en fait ceci est un pointeur
sur un tableau de 10 entiers, ce qui n'est pas ce que je veux.


Merci encore