OVH Cloud OVH Cloud

Retour chaine litterale

46 réponses
Avatar
candide
Bonjour

Le code suivant est correct je pense :

char *f(void)
{
char *ok="OK";
return ok;
}

Et le suivant l'est-il

char *f(void)
{
return "OK";
}

?

Je dirais que oui (en plus, pas de warning) mais quand même j'ai un doute : bien
que les chaînes littérales soient en mémoire statique, le compilateur va-t-il
retourner la même adresse à chaque appel ? Bon en fait quand on dit que les
chaînes sont en mémoire statique, je trouve que c'est un peu vague. La Norme,
elle, dit :

A character string literal has static storage duration and type
"array of char ,"

mais dans un programme on écrit

int toto=42, titi;
titi=toto + strlen("zozo");

le compilateur place-t-il en mémoire statique la chaîne "zozo" parce que je vois
pas l'intérêt de le faire ? Par contre si on écrit

char *s="zozo";

je vois l'intérêt puisque l'adresse est utilisée par une variable


D'ailleurs, dans le premier exemple, la variable ok a-t-elle toujours la même
valeur ? Je crois que oui mais j'ai un petit doute.


Merci.

10 réponses

1 2 3 4 5
Avatar
candide
Pierre Maurette a écrit :
candide, le 14/07/2009 a écrit :
Pierre Maurette a écrit :
candide, le 13/07/2009 a écrit :





[...]

Il n'y
a pas d'objet à copier.



La question est de savoir si "OK" existe en mémoire ou pas. J'avais crû
comprendre qu'il n'y avait pas de garantie que l'objet n'existe pas :



Le code qui nous occupe est le suivant:

char *h(void)
{
char ok[]="OK";
return ok;
}

Si on outrepasse les warnings et qu'on compile quand même cet étrange
code, "OK" peut effectivement /exister/ pendant quelques nanosecondes en
mémoire locale



Je crois que la discussion devient byzantine et qu'on va bientôt aborder la
question du sexe des chaînes. Bon, moi j'avais compris que les chaînes
littérales ("truc") étaient systématiquement
placées en mémoire statique même si l'adresse n'était pas utilisée ou nécessaire
(par exemple sizeof "truc"; ou char ok[]="OK";) et même d'après la Norme c'est
en phase 7. Après, à quoi servent ces tableaux en mémoire statique lorsque
l'adresse de la chaîne littérale n'est pas utile ? ça en fait je n'en sais rien.
Comme tu l'as rappelé, char ok[]="OK"; revient à initialiser le tableau ok
avec 3 caractères 'O', 'K' et 0, c'est vrai donc qu'on s'en fout de la chaîne
"OK" en mémoire statique. Par contre, si on a char *ok="OK"; là on ne s'en fout
pas puisque le tableau est converti en pointeur, d'ailleurs je suppose qu'on
aurait pu écrire de façon équivalente : char *p=&"OK"[0];
Avatar
Eric Levenez
Le 14/07/09 00:00, dans <4a5bae81$0$421$, « candide »
a écrit :

Sauf que je ne vois pas comment on peut réutiliser le retour de f puisque
l'objet renvoyé n'existe plus ou n'est plus censé exister d'ailleurs la Norme
dit :
[snip]



char *p = malloc(10);
printf("%pn", p);
free(p);
printf("%pn", p);

Donc d'après toi le code précédent ne va pas afficher 2 fois la même chose
et une opération magique va changer la valeur de la variable locale p au
moment du free ?

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
Richard Delorme
Le 14/07/2009 10:43, Eric Levenez a écrit :
Le 14/07/09 00:00, dans<4a5bae81$0$421$, « candide »
a écrit :

Sauf que je ne vois pas comment on peut réutiliser le retour de f puisque
l'objet renvoyé n'existe plus ou n'est plus censé exister d'ailleurs la Norme
dit :
[snip]



char *p = malloc(10);
printf("%pn", p);
free(p);
printf("%pn", p);

Donc d'après toi le code précédent ne va pas afficher 2 fois la même chose
et une opération magique va changer la valeur de la variable locale p au
moment du free ?



D'accord, printf affichera la même chose les deux fois, mais en
pratique, je ne vois pas l'intérêt d'un pointeur que l'on ne peut pas
déférencer (sauf comme borne d'un tableau).

--
Richard
Avatar
Richard Delorme
Le 14/07/2009 10:55, Richard Delorme a écrit :

char *p = malloc(10);
printf("%pn", p);
free(p);
printf("%pn", p);

Donc d'après toi le code précédent ne va pas afficher 2 fois la même
chose
et une opération magique va changer la valeur de la variable locale p au
moment du free ?



D'accord, printf affichera la même chose les deux fois,



En fait, ce n'est même pas obligé. D'après la norme, la valeur du
pointeur devient indéterminé quand l'objet qu'il pointe n'existe plus.

§ 6.2.4.2 [...] The value of a pointer becomes indeterminate when the
object it points to reaches the end of its lifetime.

mais en
pratique, je ne vois pas l'intérêt d'un pointeur que l'on ne peut pas
déférencer (sauf comme borne d'un tableau).



--
Richard
Avatar
-ed-
On 13 juil, 16:53, Pierre Maurette wrote:
A peu près autant que la rose de Malherbe, l'espace d'un matin. Je vous
emmerde...



grossièreté inutile ...
Avatar
espie
In article ,
Pierre Maurette wrote:
candide, le 13/07/2009 a écrit :
Merci à vous trois de vos réponses.

Je me réjouis que Pierre Maurette et Emmanuel Delahaye soient capables de
tenir une conversation cordiale avec moi ;)



Vous vous trompez. Là aussi.

... le tout étant de savoir combien de temps ça va durer ... ;)



A peu près autant que la rose de Malherbe, l'espace d'un matin. Je vous
emmerde...



Si candide t'insupporte, utile un kill-file...

c'est vrai qu'il a des cotes jeune chiot rebelle passablement enervants,
mais qunad meme !
Avatar
-ed-
On 13 juil, 17:48, Pierre Maurette wrote:
> OK. Dans le même genre il y a quelque chose qui peut troubler le dé butant,
> c'est l'absence de warning ici :

> int *f(void)
> {
> int okB;
> int *p=&ok;
> return p;
> }

Il n'y a pas de vrai problème dans ce code.



Bah, on retourne l'adresse d'un objet qui n'existe plus ... A part ça
tout va bien ...

La fonction retourne [une
copie de] la valeur du int* p. p a été initialisé par &ok, le
programmeur exprime clairement sa volonté de faire ainsi. &ok est une
*valeur numérique immédiate*, résolue éventuellement après la
compilation, au niveau du lieur ou du loader, mais peu importe.



C'est une adresse invalide après le return...


J'ajoute:
Le même raisonnement s'applique à:

char *h(void)
{
    char ok[]="OK";
    char* dummy = ok;
    return dummy;

}

qui ne génère pas de warning. On exprime encore clairement sa volont é
de retourner une copie de valeur.



... de coder une ânerie ... Tu devrais relire ton livre, je suis sûr
que c'est expliqué ...

C'est peut-être un peu comme un
if(a=b){} qui va warner, alors que if((a=b) != 0){} voire if((a=b )){}
vont faire taire le warning: je ne double pas les parenthèses par
plaisir...



pfff... strictement aucun rapport...

Tu nous avais habitué à de meilleurs raisonnements... l'age, sans
doute ...
Avatar
-ed-
On 14 juil, 00:40, Pierre Maurette wrote:
candide, le 14/07/2009 a écrit :



> Pierre Maurette a écrit :

>>> OK. Dans le même genre il y a quelque chose qui peut troubler le
>>> débutant, c'est l'absence de warning ici :

>>> int *f(void)
>>> {
>>> int okB;
>>> int *p=&ok;
>>> return p;
>>> }

>> Il n'y a pas de vrai problème dans ce code.

> Sauf que je ne vois pas comment on peut réutiliser le retour de f pui sque
> l'objet renvoyé n'existe plus ou n'est plus censé exister

On se fout de l'objet. On dispose de la valeur d'un int*. On peut
faire:
printf("%pn", f());
sans danger...



Oui, afficher la valeur est techniquement possible. Mais parfaitement
inutile. De plus, un pingouin de passage pourrait être tenté de
déréférencer le pointeur et là, c'est le drame...

printf("%dn", *f());
Avatar
Eric Levenez
Le 14/07/09 11:17, dans <4a5c4d87$0$17767$,
« Richard Delorme » a écrit :

Le 14/07/2009 10:55, Richard Delorme a écrit :

char *p = malloc(10);
printf("%pn", p);
free(p);
printf("%pn", p);

Donc d'après toi le code précédent ne va pas afficher 2 fois la même
chose
et une opération magique va changer la valeur de la variable locale p au
moment du free ?



D'accord, printf affichera la même chose les deux fois,



En fait, ce n'est même pas obligé. D'après la norme, la valeur du
pointeur devient indéterminé quand l'objet qu'il pointe n'existe plus.

§ 6.2.4.2 [...] The value of a pointer becomes indeterminate when the
object it points to reaches the end of its lifetime.



Et tu connais une plateforme où, dans mon exemple, la variable locale p est
modifiée entre les 2 print ?

J'imagine bien une appli avec pleins de malloc où les adresses sont stockées
dans des structures, et un free fait que de façon immédiate quelque chose
change tous les pointeurs des structures pour rendre "indéterminé" ces mêmes
pointeurs.

mais en
pratique, je ne vois pas l'intérêt d'un pointeur que l'on ne peut pas
déférencer (sauf comme borne d'un tableau).





Oui, il n'y a pas d'intérêt, et c'est peut-être pour cela que la norme
possède la phrase floue que tu cites. Ce fameux principe de précaution qui
permet tous les excès.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
Pierre Maurette
Richard Delorme, le 14/07/2009 a écrit :
Le 14/07/2009 10:55, Richard Delorme a écrit :

char *p = malloc(10);
printf("%pn", p);
free(p);
printf("%pn", p);

Donc d'après toi le code précédent ne va pas afficher 2 fois la même
chose
et une opération magique va changer la valeur de la variable locale p au
moment du free ?



D'accord, printf affichera la même chose les deux fois,



En fait, ce n'est même pas obligé. D'après la norme, la valeur du pointeur
devient indéterminé quand l'objet qu'il pointe n'existe plus.

§ 6.2.4.2 [...] The value of a pointer becomes indeterminate when the object
it points to reaches the end of its lifetime.



J'imagine que ça peut être effectif pour un pointeur qui serait un
offset par rapport à un "truc" qui changerait, ou une entrée dans une
table. A ce moment-là l'affichage par %p risque de foirer. Mais la
variable pointeur (ou celle contenant une copie de sa valeur dans
l'exemple initial) a toujours une valeur numérique qu'on peut afficher
en castant en intptr_t ou uintptr_t. Effectivement ça ne sert à priori
pas à grand-chose, ou alors dans une démarche de débogage ?


--
Pierre Maurette
1 2 3 4 5