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

1 2 3 4 5
Avatar
espie
In article <47dc1f9c$0$2621$,
candide wrote:
Oui, tu m'as dit d'essayer quel truc _précisément_ ("jouer avec son
compilateur" est une mauvaise réponse) ?


Tu compares le code machine genere pour

char a[] = "bonjour";

et

char *b = "bonjour";

je te laisse trouver tout seul quelles options utiliser pour trouver cette
info.

Avatar
Jean-Marc Bourguet
candide writes:

int toto[5];

réserve de l'espace pour 5 entiers mais qu'elle n'entraîne pas de
réservation d'espace pour toto lui-même bien que l'objet toto existe,


L'objet toto ce sont ces 5 entiers.

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
candide

Il y a deux contextes qui admettent un argument tableau:
sizeof et &."


C'est volontairement que tu omets le 3ème cas cité par la norme :




---------------------------6.3.2.1-----------------------------------
Except when it is the operand of the sizeof operator or the unary &
operator , or is a string literal used to initialize an array, an
expression that has type array of type is converted to an expression
with type pointer to type that points to the initial element of the
array object
---------------------------6.3.2.1-----------------------------------



?

Je pose la question car c'est souvent ainsi formulé, par exemple
Harbison & Steele dit (page 140) :


----------------------------------------------------------------------
"The only exceptions to this conversion rule is when the array
identifier is used as an operand of the sizeof or adress (&) operators,
in wich case (...)"
----------------------------------------------------------------------

et je me dis qu'il doit y avoir une raison.

Avatar
candide


Tu compares le code machine genere pour

char a[] = "bonjour";

et

char *b = "bonjour";

Ah oui, exact. Bon, il faut savoir lire de l'assembleur pour ça ?


Avatar
Jean-Marc Bourguet
candide writes:


Il y a deux contextes qui admettent un argument tableau:
sizeof et &."


C'est volontairement que tu omets le 3ème cas cité par la norme :


Non.

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
Marc Boyer
On 2008-03-15, candide wrote:
D'accord mais alors comment l'implémentation fait-elle pour convertir
implicitement un tableau en pointeur, faut bien qu'elle trouve l'adresse
quelque part ?


Ben oui, le compilateur la calcule, mais ensuite, dans
le code généré, il n'y a aucun besoin de la conserver.

Par exemple:
double foo(void){
double p[10];
double q[10];
double r[10];

p[6]= 1.0;
q[3]= 3.0;
r[4]= 4.0;
return p[6]+q[3]+r[4];
}
Aucun besoin pour le compilo de laisser dans l'exécutable
les adresses de début de p, q et r. Il génère trois accès en
lecture/écriture sur trois adresses. Les adresses des tableaux
sont oubliées.

Dans le même genre
void bar(double d){
double x;
double t[5];
x= 0;
for(int i=0;i<5;++i){
t[i]= i+1;
d+= t[i];
}
}
et
void bar(double d){
double t[6];
t[0]= 0;
for(int i=1;i<6;++i){
t[i]= i;
t[0]+= t[i];
}
}
risquent de donner lieu à exactement le même code, car
les accès mémoires sont surement les même, et il n'y a
aucun besoin de "stoquer" le début de t.

Marc Boyer

Avatar
espie
In article <47dc2740$0$22897$,
candide wrote:


Tu compares le code machine genere pour

char a[] = "bonjour";

et

char *b = "bonjour";


Ah oui, exact. Bon, il faut savoir lire de l'assembleur pour ça ?


Non, pas forcement. Une comprehension tres partielle suffit a voir
la difference.


Avatar
candide
candide writes:

int toto[5];

réserve de l'espace pour 5 entiers mais qu'elle n'entraîne pas de
réservation d'espace pour toto lui-même bien que l'objet toto existe,


L'objet toto ce sont ces 5 entiers.


OK, je commence à me dire que je n'avais pas tout compris sur les
tableaux. Pourtant j'aurais dit que ce tu disais était le contenu de
l'objet :


----------------------3.14---------------------------------------
object
region of data storage in the execution environment, the contents of
which can represent values
--------------------------------------------------------------------

Ce qui me gêne, c'est que dans


int toto[5]={0};
int titi[5]={0};

titi et toto seraient donc le même objet alors qu'ils représentent des
zones de stockage différentes.

Alors, finalement un tableau, ça n'existe pas !!!! ce qui existe c'est
un objet tableau, un identificateur de tableau et la valeur d'un
tableau. Ou je délire complètement ?


Avatar
Francois
L'esprit de la règle c'est "Dans les contextes qui ne peuvent pas prendre
un tableau, celui-ci est converti implicitement en un pointeur vers son
premier élément. Il y a deux contextes qui admettent un argument tableau:
sizeof et &."


Et bien, ceci me convient bien. J'avais l'impression que c'est ce que je
voulais dire. Sans doute l'ai-je mal dit, tout ça n'est peut-être qu'une
histoire de formulation ? Une seule petite chose me gêne, c'est dit
comme ça on a l'impression que l'on pourrait mettre "tab" (où on a "int
tab[10]) à gauche du symbole "=", comme on peut le faire pour un
pointeur. Or, bien sûr c'est impossible avec "tab".


Alors là vous me parlez de tableaux que je qualifierais "d'exotiques".


Quel importance? Tu me semble attacher trop d'importance à la manière dont
tu obtiens un tableau. Que ce soit le contenu d'une variable ou par une
expression compliquée, cela ne change rien.


Je ne disais pas ça pour vous contredire, loin de là. C'est juste que je
n'ai pas encore le même degré d'abstraction que vous. Chez moi, ces
notions sont encore bien fragiles. Mais je comprends parfaitement ce que
vous voulez dire, le concept de tableau est indépendant de la nature de
ces éléments (et en relisant, je trouve que j'ai fait preuve d'un peu de
paresse intellectuelle).


Ne serait-ce pas plutôt « int t2[2][10]; » au début pour la déclaration du
tableau ?


Non. La première taille peut être n'importe quoi de supérieur à 2 sans
rien changer à ce que j'ai écrit, mais pas inférieur ou égal à 2.


Pardon, pardon. You absolutely right !


tu ne peux pas faire cela pas plus que tu ne peux faire &tab[0] = &tab[0]
+ 1 ou x+1 = x+3.
Là aussi, j'ai l'impression (peut-être à tort) que vous chercher à

rectifier une erreur de ma part.


Tu donnes l'impression de croire qu'il y a quelque chose de particulier
pour les variables de type tableau (voir le sujet du fil). Il y a quelque
chose de particulier pour les expressions de type tableau (la plupart du
temps elles se prennent une conversion implicite dans les pattes), mais
rien de plus pour les variables.


Ah, il est possible que je donne cette impression car je ne sais pas du
tout ce qu'est "variable de type tableau" et "expression de type
tableau". Serait-ce trop demander que d'avoir un exemple. Là je suis
perdu et rattrapé par mon manque de vocabulaire. Allez, je tente quelque
chose :

Avec "int tab[10] ;"
- "variable de type tableau" ---> tab[2]
- "expression de type tableau" ---> tab

Est-ce juste ?



François



Avatar
candide


Ben oui, le compilateur la calcule, mais ensuite, dans
le code généré, il n'y a aucun besoin de la conserver.

Par exemple:
double foo(void){
double p[10];
double q[10];
double r[10];

p[6]= 1.0;
q[3]= 3.0;
r[4]= 4.0;
return p[6]+q[3]+r[4];
}
Aucun besoin pour le compilo de laisser dans l'exécutable
les adresses de début de p, q et r.




D'accord, je n'avais pas pensé à ce genre d'exemples, après tout c'est
vrai, il suffit que le compilateur écrive le code qui permette
l'exécution de la fonction foo() par quel que moyen que ce soit.



Dans le même genre
void bar(double d){
double x;
double t[5];
x= 0;
for(int i=0;i<5;++i){
t[i]= i+1;
d+= t[i];
}
}
et
void bar(double d){
double t[6];
t[0]= 0;
for(int i=1;i<6;++i){
t[i]= i;
t[0]+= t[i];
}
}
risquent de donner lieu à exactement le même code, car
les accès mémoires sont surement les même, et il n'y a
aucun besoin de "stoquer" le début de t.



OK, je crois que je n'avais pas perçu le degré de liberté que possède le
compilateur.
Il me semble même que le compilateur peut ne pas générer le code d'une
fonction qui ne fait rien.

1 2 3 4 5