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

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

5 6 7 8 9
Avatar
candide

"cdecl". C'est incroyable le nombre de petits programmes "amusants"
qu'il y a sur Linux.


Tu découvriras un jour par exemple Valgrind, gdb (qui n'est pas un petit
programme), etc.



Tout à l'heure, quelqu'un a évoqué un programme
nommé "indent" pour indenter du code. Ca marche impeccable ce truc, j'ai
testé sur un code non indenté, c'est surprenant.


Oui mais si tu veux une indentation très customisé, c'est pas si évident
à obtenir.

Il existe aussi des indenteurs en ligne (j'en avais signalé un certain
nombre sur le forum C du siteduzero).


Sur ton premier lien, je vois "int (*fpf())();". Ca existe des truc
comme ça dans "la vraie vie" ?



Je pense que oui (on arrive vite à faire des abstractions qui
necessitent des déclarations compliquées) mais d'autres sont mieux
placés que moi pour répondre. L'exemple classique est la fonction
standard signal() dont le prototype est

void (*signal(int sig, void (*func)(int)))(int) .

Néanmoins, K&R disent :

----------------------
Although truly complicated declarations rarely arise in practice, it is
important to know how to understand them,
----------------------



en était une réédition plus récente. On dirait que oui, mais le titre
n'est pas exactement le même et en plus il est moins cher que "La
référence du C norme ANSI-ISO"


J'ai fait exprès de choisir l'ancien titre sinon on le confond avec ses
deux autres ouvrages qui n'ont rien à voir car de bien moins grande
ampleur. Delannoy est plutôt décrié en tant qu'auteur sur le langage C++
mais je trouve ce livre sur le C très soigné (le plus soigné que je
connaisse, anglais et français confondus), si tu veux en savoir
davantage, regarde ce que j'en avais dit sur le forum C du siteduzero
(utiliser leur moteur de recherche), il est vrai que je n'ai pourtant
pas été tendre avec lui.


(bien que plus récent!).


Le marketing a encore frappé, il nous ont fait le même coup avec
l'édition française du K&R.


Tu peux lire sur l'édition 2002, retirage 2005 :
"Publié à l'origine sous le titre etc"
"reconditionnement"
"nouvelle couverture, nouveau prix"
"Le texte de l'ouvrage reste inchnagé par rapport au tirage précédent".

A mon avis ce bouquin pourrait te plaire, il est super détaillé mais
difficile à suivre quand même, maintenant ça va beaucoup mieux mais avec
un an de C, j'ai eu beaucoup de mal à suivre avec tout metalangage qu'il
utilise, enfin, tu m'as l'air plus doué toi.

Avatar
Marc Boyer
On 2008-03-19, candide wrote:
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.


Je pense que ça se discute : je comprends assez bien le français, je
l'écris à peu près correctement, je suis sensible au choix des mots, je
peux faire des analogies avec d'autres langues et pourtant je n'ai
jamais rien entravé au latin ni à l'ancien français,
[SNIP]


Oui, mais il faut combien d'années pour apprendre à parler français ?
Ceci dit, comme le disait un contributeur régulier, Gabriel, "Proof
by analogy is a fraud".

C'est néanmoins difficile comme question: la plupart des formations
un peu approfondies sur le C comportent aussi une part
d'archi/assembleur, et la plupart des autodidactes qui ont une
quarantaine d'année ont fait de l'assembleur, car c'était encore assez
"à la mode" il y a de cela, je dirais, 15 ans.
De plus, les fondements de l'archi des proc et des compilos sont
quand même bien plus simples que les détails de la norme C.

Et puis, que signifie "faire honnêtement du C" ?
Tant qu'on ne cherche pas la portabilité, c'est pas trop dur.
Et pendant des années, des sociétés ont pu vivre en vendant des
logiciels uniquement compatible Win32 compilables uniquement
avec VC++. C'est peut-être encore le cas, d'ailleurs.


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
Jean-Marc Bourguet
Marc Boyer writes:

Tant qu'on ne cherche pas la portabilité, c'est pas trop dur.
Et pendant des années, des sociétés ont pu vivre en vendant des
logiciels uniquement compatible Win32 compilables uniquement
avec VC++.


Tu oublies de preciser la version: 6.0.

C'est peut-être encore le cas, d'ailleurs.


Toujours a lire ce qu'on trouve sur Internet. Et toujours avec la meme
version de VC++ parce que les suivantes ont change des choses et que ca
compile plus ou ca ne s'execute pas bien.

A+

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

Avatar
candide

Et puis, que signifie "faire honnêtement du C" ?
Tant qu'on ne cherche pas la portabilité, c'est pas trop dur.


Moi ce qui m'intéresse c'est d'être capable d'écrire du C _portable_ ,
Au passage, je dis bien "être capable" (cf. le "il peut le faire" de
Pierre Dac je crois).

Avatar
candide

Oui, mais il faut combien d'années pour apprendre à parler français ?
Ceci dit, comme le disait un contributeur régulier, Gabriel, "Proof
by analogy is a fraud".


Oui, ou en bon français, "comparaison n'est pas raison". De toute façon,
je n'ai pas parlé de "prouver", j'ai dit que l'_avis_ prononcé par JMB
"se discute". En matière d'apprentissage, l'utilisation d'"analogies"
est courant. Quand tu utilises des exemples (la norme en utilise), tu
permets de mieux cerner un objet et tu procèdes par analogie. Une preuve
qui serait basée sur une analogie serait peut-être abusive mais bien
souvent pour faire comprendre (et même bâtir) une preuve on procède par
analogie.

J'ai même été étonné de voir que la norme appuie certaines de ses
définitions ou de ce qui peut être considéré comme tel sur un exemple.

Ainsi :


An integer character constant is a sequence of one or more multibyte
characters enclosed in single-quotes, as in 'x'.
_____________________________________^^^^^^^^^^^^

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

Et puis, que signifie "faire honnêtement du C" ?
Tant qu'on ne cherche pas la portabilité, c'est pas trop dur.


Moi ce qui m'intéresse c'est d'être capable d'écrire du C _portable_ ,
Au passage, je dis bien "être capable" (cf. le "il peut le faire" de
Pierre Dac je crois).


Donc, je pense que c'est possible.
Mais chaque fois que tu demanderas "pourquoi" ou que tu feras
des suppositions (comme ta supposition que l'adresse de début
d'un tableau devait être stoquée quelque part), les réponses
seront surement liées au fonctionnement du compilo et/ou du
processeurs.
Et à force, tu apprendras un peu comment fonctionne un
processeur ou un compilateur.


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
Antoine Leca
[ Désolé du retard : mon serveur s'est bloqué la semaine dernière, puis j'ai
été pris apr les congés, qui ici à Valence s'étendent cette année du 19 au
24 mars... :+)
Donc ce message a été rédigé le 18. ]

En news:47dea0e9$0$16130$, Francois va escriure:
"int tab2[10][12];",
L'occurrence, il faudrait dire comment exactement ? "tab2" est une
variable de type tableau de *10x12 int* ?


Non : les tableaux multi-dimensionnels n'existent pas en C. tab2 est
le nom d'une variable de type tableau de 12 tableaux de 10 entiers.


Alors, est-ce que par hasard ce ne serait pas plutôt « une variable de
type tableau de 10 tableaux de 12 entiers » ?


C'est bien, tu as bien suivi :^)


Petite question : en interne (1) c'est les "[]" qui sont convertis
avec des "*" ou (2) c'est l'inverse.


Cela dépend.

Sur un compilateur que je connais un peu (lcc), les deux sont convertis en
INDIRI4, avec éventuellement un ADDI4 en dessous, ce qui correspond grosso
modo à ton (1). Mais un des gros inconvénients de lcc est qu'il n'est pas
facile de repérer les possibilités d'utilisation des modes d'adresages
indexés (ceux qui sont les traductions directes de la forme []). D'autres
compilateurs (et en particulier les compilateurs originaux, celui de D.
Ritchie et le pcc de S.Johnson) recherchent pour des questions de
performances à utiliser le plus souvent les adressages indexés : deux
possibilités pour cela, ou bien on garde chacune des deux formes, et [] mène
à un adressage indexé alors que * mènera à une indirection « bête », mais là
on perd nombre de possibilités d'optimisation ; ou bien le compilateur
cherche si possible à former les adressage indexés, et la manière la plus
simple est d'utiliser la méthode (2) ci-dessus !


pour moi un nom est simple cas particulier d'expression. (?)


Pas seulement. Un nom détermine l'obtention d'une valeur et un type, comme
une expression, mais c'est aussi un déterminant de la durée de vie et de la
« liaison » (static indique une liaison interne à l'unité de compilation, le
nom désigne donc un même objet quel que soit l'endroit), donc cela renvoit à
la perénité et à la réusabilité, donc aux problèmes d'alias.


Antoine



Avatar
Antoine Leca
[ Désolé du retard : mon serveur s'est bloqué la semaine dernière, puis j'ai
été pris apr les congés, qui ici à Valence s'étendent cette année du 19 au
24 mars... :+)
Donc ce message a été rédigé le 18. ]

En news:47dea0e9$0$16130$, Francois va escriure:
"int tab2[10][12];",
L'occurrence, il faudrait dire comment exactement ? "tab2" est une
variable de type tableau de *10x12 int* ?


Non : les tableaux multi-dimensionnels n'existent pas en C. tab2 est
le nom d'une variable de type tableau de 12 tableaux de 10 entiers.


Alors, est-ce que par hasard ce ne serait pas plutôt « une variable de
type tableau de 10 tableaux de 12 entiers » ?


C'est bien, tu as bien suivi :^)


Petite question : en interne (1) c'est les "[]" qui sont convertis
avec des "*" ou (2) c'est l'inverse.


Cela dépend.

Sur un compilateur que je connais un peu (lcc), les deux sont convertis en
INDIRI4, avec éventuellement un ADDI4 en dessous, ce qui correspond grosso
modo à ton (1). Mais un des gros inconvénients de lcc est qu'il n'est pas
facile de repérer les possibilités d'utilisation des modes d'adresages
indexés (ceux qui sont les traductions directes de la forme []). D'autres
compilateurs (et en particulier les compilateurs originaux, celui de D.
Ritchie et le pcc de S.Johnson) recherchent pour des questions de
performances à utiliser le plus souvent les adressages indexés : deux
possibilités pour cela, ou bien on garde chacune des deux formes, et [] mène
à un adressage indexé alors que * mènera à une indirection « bête », mais là
on perd nombre de possibilités d'optimisation ; ou bien le compilateur
cherche si possible à former les adressage indexés, et la manière la plus
simple est d'utiliser la méthode (2) ci-dessus !


pour moi un nom est simple cas particulier d'expression. (?)


Pas seulement. Un nom détermine l'obtention d'une valeur et un type, comme
une expression, mais c'est aussi un déterminant de la durée de vie et de la
« liaison » (static indique une liaison interne à l'unité de compilation, le
nom désigne donc un même objet quel que soit l'endroit), donc cela renvoit à
la perénité et à la réusabilité, donc aux problèmes d'alias.


Antoine



Avatar
Pierre Maurette

[...]

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


Oui. Ou en *(3 + *(1+tab)). Mais il est beaucoup plus lisible d'écrire
1[tab][3] ou mieux 3[1[tab]].

--
Pierre Maurette

Avatar
Pierre Maurette
Francois writes:

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 ?


int *p[10];


Alors ça par exemple. Merci pour cette réponse rapide.


Mais la déclaration "int *p[10] ;" ne fait-elle pas de p un pointeur sur un
tableau de 10 entier plutôt ?

Où alors c'est une histoire de parenthèses implicites et de règles de
priorité peut-être ?

"int *(p[10]) ;" déclare p comme un tableau de 10 pointeurs sur des entiers.

"int (*p)[10] ;" déclare p comme un pointeur sur un tableau de 10 entiers.

Est-ce juste ? A moins que ce soit exactement l'inverse ? J'ai un peu de mal
avec les déclarations de pointeurs.


On peut écrire (parmi d'autres plus délirants):
int *a = NULL;
int * a = NULL;
int* a = NULL;

Personnellement, mais ce n'est sans doute pas un BON conseil, je
préfère la troisième, et surtout je lis: a est un int*. Un peu comme:

typedef int* pint;
pint a = NULL;

La première forme, ou le "déplacement" du '*', me sert (m'a servi) de
mnémotechnique pour: *a est un int.

Lire:
int* p[10];
est alors sans doute plus facile au débutant.

La raison pour laquelle ce n'est pas un bon conseil, c'est le danger de
faire la faute:

int* a, b;

Notez quand même que la ligne précédente ne devrait pas être écrite
telle quelle et que:
i
nt* a = NULL, b = NULL;

doit gueuler.
En revanche:

typedef int* pint;
pint a = NULL, b = NULL;

fonctionne comme on peut l'attendre, un typedef n'étant pas un #define.

--
Pierre Maurette



5 6 7 8 9