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

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
Eric Levenez
Le 11/07/09 17:04, dans <4a58aa11$0$10847$,
« candide » a écrit :

Le code suivant est correct je pense :

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



Oui. Un "const char" à la place des "char", c'est mieux.

Et le suivant l'est-il

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



Oui. Un "const char" à la place du "char", c'est mieux.

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 ?



Oui.

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 totoB, 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 ?



Les chaînes de caractères sont généralement placées dans des zones en
lecture seule, ce qui n'était pas le cas il y a bien longtemps. Il existe
des options sur certains compilateurs pour indiquer ce que l'on veut faire.

Par contre si on écrit

char *s="zozo";

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



Là je ne vois pas ta logique. Dans les deux cas l'adresse de la chaîne est
utilisée (par une fonction dans ton premier exemple et par une variable dans
le second), donc il faut qu'elle soit allouée en mémoire.

Si tu sous-entends que strlen("toto") doit être remplacé par 4 par le
compilateur, cela n'est pas évident car strlen peut être une fonction de
l'utilisateur qui fait tout autre chose que ce que fait la fonction de la
norme C, même si ce n'est pas bien, c'est courant. Je suppose que certains
compilateurs osent faire ce genre d'optimisation en supposant que strlen est
une fonction "buildin", mais Audiard en a parlé... :-)

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.



Oui.

De plus, dans le code suivant :

const char *p = "OK";
const char *q = "OK";

Le compilateur peut très bien n'allouer qu'une fois la chaîne en mémoire et
donc p == q. Là aussi cela dépend des compilateurs et des options de
compilations. Mais il ne faut pas compter là dessus pour faire un programme
portable.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
-ed-
On 11 juil, 17:04, candide wrote:
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";

}



Les deux sont identiques (et probablement codés de la même façon en
asm) et aussi douteux :

Compiling: main.c
C:devhellomain.c: In function `fa':
C:devhellomain.c:3: warning: initialization discards qualifiers
from pointer target type
C:devhellomain.c: In function `fb':
C:devhellomain.c:10: warning: return discards qualifiers from
pointer target type
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 2 warnings

Je dirais que oui (en plus, pas de warning) mais quand même j'ai un dou te : bien
que les chaînes littérales soient en mémoire statique,



Elles sont en mémoire "permanente" (la durée de vie est celle du
programme). Rien ne dit qu'il s'agisse de la mémoire statique (donc
modifiable). Ca pourrait très bien être une adresse correspondant à d e
la mémoire en lecture seule voire à de la ROM (c'est souvent le cas en
embarqué). Le 'const' n'est pas une option... Ceci est correct :

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

char const *fb (void)
{
return "OK";
}


Compiling: main.c
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 0 warnings



le compilateur va-t-il
retourner la même adresse à chaque appel ? Bon en fait quand on dit q ue les



Oui.

chaînes sont en mémoire statique, je trouve que c'est un peu vague.



C'est même carrément faux.

La Norme,
elle, dit :

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



"duration" fait toute la différence. "static storage duration"
signifie "de durée de vie permanente". Ca ne donne aucune indication
sur la classe de stockage qui dépend de l'implémentation.

mais dans un programme on écrit

int totoB, 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 ?



Il la place où il veut. Ici, il pourrait très bien remplacer strlen
("zozo") par 4, directement, selon son degré d'optimisation et
d'intelligence... Il n'y aurait donc pas de chaine "toto" en mémoire
permanente (aka 'de durée de vie "statique"')..

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.



La variable en question n'est probablement même pas codée, et le
premier code se comporte exactement comme le second...
Avatar
candide
-ed- a écrit :
On 11 juil, 17:04, candide wrote:
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";

}



Les deux sont identiques (et probablement codés de la même façon en
asm) et aussi douteux :




douteux ?



Compiling: main.c
C:devhellomain.c: In function `fa':
C:devhellomain.c:3: warning: initialization discards qualifiers
from pointer target type
C:devhellomain.c: In function `fb':
C:devhellomain.c:10: warning: return discards qualifiers from
pointer target type
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 2 warnings





Ben moi j'ai aucun warning et mes options ne sont pas laxistes :

gcc -W -Wall -stdÉ9 -pedantic



Elles sont en mémoire "permanente" (la durée de vie est celle du
programme). Rien ne dit qu'il s'agisse de la mémoire statique (donc
modifiable).



Ben, mémoire permanente, c'est pas pareil que mémoire statique ?


6.2.4 Storage durations of objects
(...)
An object whose identifier is declared with external or internal linkage, or with
the storage-class specifier static has static storage duration. Its lifetime is
the entire execution of the program and its stored value is initialized only
once, prior to program startup.

Et puis tu fais une fixation sur cette histoire de modifiable.


Ca pourrait très bien être une adresse correspondant à de
la mémoire en lecture seule voire à de la ROM (c'est souvent le cas en
embarqué). Le 'const' n'est pas une option...



Ben si, rien ne m'y oblige dans la Norme. Je fais que donner un exemple, ya une
vie en dehors de l'embarqué (et en dehors de la Norme aussi, je sais), non ?



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

char const *fb (void)
{
return "OK";
}


Compiling: main.c
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 0 warnings





Content ?




le compilateur va-t-il
retourner la même adresse à chaque appel ? Bon en fait quand on dit que les



Oui.

chaînes sont en mémoire statique, je trouve que c'est un peu vague.



C'est même carrément faux.



En quoi ?



La Norme,
elle, dit :

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



"duration" fait toute la différence. "static storage duration"
signifie "de durée de vie permanente". Ca ne donne aucune indication
sur la classe de stockage qui dépend de l'implémentation.




Oui mais ça c'est un autre problème, la "classe de stockage" comme tu dis, c'est
juste de la syntaxe (c'est le spécificateur static). Pour moi mémoire statique
fait référence à la _durée_ de vie. Après c'est toi qui viens rajouter une
notion de mémoire à lecture seule qui n'existe pas dans la Norme et qui doit
avoir un sens suivant les implémentations. La Norme dit juste qu'on ne peut pas
modifier une chaîne littérale ou un objet const (pour être exact, la Norme
utilise juste dans un exemple le terme de "read-only").


mais dans un programme on écrit

int totoB, 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 ?



Il la place où il veut. Ici, il pourrait très bien remplacer strlen
("zozo") par 4, directement, selon son degré d'optimisation et
d'intelligence... Il n'y aurait donc pas de chaine "toto" en mémoire
permanente (aka 'de durée de vie "statique"')..




OK, merci mais j'ai du mal à suivre le vocabulaire que tu utilises.
Avatar
candide
Eric Levenez a écrit :
Le 11/07/09 17:04, dans <4a58aa11$0$10847$,
« candide » a écrit :

Le code suivant est correct je pense :

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



Oui. Un "const char" à la place des "char", c'est mieux.



Dit comme cela, je l'accepte volontiers.

Sinon, concernant le code que j'ai écrit, ok est une variable locale qui renvoie
l'adresse d'un objet statique, donc ça ne pose pas de problème de retour. En
revanche celui-ci en pose :

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


comme me le confirme le compilateur alors que l'action est la même. Vous allez
peut-être me dire que l'adresse de "OK" n'est pas forcément la même que la
valeur de ok et donc que peut-être "OK" est recopié provisoirement.


Et le suivant l'est-il

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



Oui. Un "const char" à la place du "char", c'est mieux.




OK mais je n'ai pas souvent vu cela (ce qui évidemment ne prouve rien ! ;) ).
Mais alors pourquoi le prototype de strchr() n'est-il pas :

const char *strchr(const char *s, int c);

au lieu de

char *strchr(const char *s, int c);

?




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 totoB, 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 ?



Les chaînes de caractères sont généralement placées dans des zones en
lecture seule, ce qui n'était pas le cas il y a bien longtemps. Il existe
des options sur certains compilateurs pour indiquer ce que l'on veut faire.

Par contre si on écrit

char *s="zozo";

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



Là je ne vois pas ta logique. Dans les deux cas l'adresse de la chaîne est
utilisée (par une fonction dans ton premier exemple et par une variable dans
le second), donc il faut qu'elle soit allouée en mémoire.



Oui, j'aurais dû prendre sizeof au lieu de strlen. Je comprends que tu ne
comprennes pas ma logique mais ça reste troublant que "zozo" soit un objet qui
ait une adresse mémoire surtout si on n'a pas besoin de l'adresse (si c'est
jsute pour compter le nombre de caractères). Quand on écrit

int zB;

on ne se pose pas la question de savoir où la r-value 42 se trouve en mémoire.



Si tu sous-entends que strlen("toto") doit être remplacé par 4 par le
compilateur, cela n'est pas évident car strlen peut être une fonction de
l'utilisateur qui fait tout autre chose que ce que fait la fonction de la
norme C, même si ce n'est pas bien, c'est courant.



Non seulement ça mais je crois que c'est interdit par la Norme.
Avatar
Pierre Maurette
candide, le 13/07/2009 a écrit :
Eric Levenez a écrit :
Le 11/07/09 17:04, dans <4a58aa11$0$10847$,
« candide » a écrit :

Le code suivant est correct je pense :

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



Oui. Un "const char" à la place des "char", c'est mieux.



Dit comme cela, je l'accepte volontiers.

Sinon, concernant le code que j'ai écrit, ok est une variable locale qui
renvoie l'adresse d'un objet statique, donc ça ne pose pas de problème de
retour. En revanche celui-ci en pose :

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


comme me le confirme le compilateur alors que l'action est la même. Vous
allez peut-être me dire que l'adresse de "OK" n'est pas forcément la même que
la valeur de ok et donc que peut-être "OK" est recopié provisoirement.



C'est beaucoup plus simple. ok est un tableau de trois char en variable
locale, et un compilo correct doit simplement vous beugler que vous
renvoyez un pointeur sur une variable locale.
char ok[]="OK";
est strictement équivalent à:
char ok[] = {'O', 'K', ''};
ou
char ok[3] = {'O', 'K', ''};

Et le suivant l'est-il

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



Oui. Un "const char" à la place du "char", c'est mieux.




OK mais je n'ai pas souvent vu cela (ce qui évidemment ne prouve rien ! ;)
). Mais alors pourquoi le prototype de strchr() n'est-il pas :

const char *strchr(const char *s, int c);

au lieu de

char *strchr(const char *s, int c);

?



Parce que la fonction est prévue pour fonctionner sur des tableaux
modifiables. Un rechercher - remplacer par exemple. Le const indique
que la fonction ne modifiera pas s, et l'utilisateur sachant ce qu'il
envoie à la fonction fera ce que bon lui semble du retour (une copie de
valeur de pointeur), en particulier l'affectera à un char* ou un const
char*.

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 totoB, 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 ?



Les chaînes de caractères sont généralement placées dans des zones en
lecture seule, ce qui n'était pas le cas il y a bien longtemps. Il existe
des options sur certains compilateurs pour indiquer ce que l'on veut faire.

Par contre si on écrit

char *s="zozo";

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



Là je ne vois pas ta logique. Dans les deux cas l'adresse de la chaîne est
utilisée (par une fonction dans ton premier exemple et par une variable dans
le second), donc il faut qu'elle soit allouée en mémoire.



Oui, j'aurais dû prendre sizeof au lieu de strlen. Je comprends que tu ne
comprennes pas ma logique mais ça reste troublant que "zozo" soit un objet
qui ait une adresse mémoire surtout si on n'a pas besoin de l'adresse (si
c'est jsute pour compter le nombre de caractères). Quand on écrit

int zB;

on ne se pose pas la question de savoir où la r-value 42 se trouve en
mémoire.



Le code:

int main(void)
{
char* s = "toto";
int z = 42;
printf("%s %dn", s, z);
return 0;
}

sera vraisemblablement compilé comme:

int main(void)
{
printf("%s %dn", "toto", 42);
return 0;
}

c'est à dire:

int main(void)
{
printf("%s %dn", 0x????, 42);
return 0;
}


et même:

int main(void)
{
char* s = "toto";
int z = 42;
printf("%p %s %dn", s, s, z);
return 0;
}

sera compilé comme:

int main(void)
{
printf("%p %s %dn", 0x????, 0x????, 42);
return 0;
}

Les valeurs 42 et 0x???? (ou le pointeur vers "toto") n'ont aucune
raison d'être créées en mémoire. Ce sont des constantes, des valeurs
immédiates, elles seront codées en dur dans le code exécutable. Genre
"mettre 42 dans tel registre", ou "empiler 42", ou "mettre 0x???? dans
registre", ou "empiler 0x????". Bien entendu, la seule différence mais
importante entre 42 et 0x???? est que 0x???? pointera vers "toto", dans
une zone de données initialisées.
Ce qui est parfois troublant, c'est le 0x????. C'est une valeur
immédiate mais qui n'a peut-être pas, contrairement à 42, de valeur
numérique connue au moment de la compilation. Cette valeur sera résolue
au cours du processus compilation - édition de liens - lancement, au
plus tard lors du lancement - ou chargement - par le loader de l'OS. Et
au moment de la génération d'un fichier image dans le cas de
l'embarqué, à priori, mais dans ce cas la valeur sera certainement
connue bien plus tôt dans le processus.
A noter que la chaîne "%p %s %dn" sera traitée exactement comme
"toto".

Si tu sous-entends que strlen("toto") doit être remplacé par 4 par le
compilateur, cela n'est pas évident car strlen peut être une fonction de
l'utilisateur qui fait tout autre chose que ce que fait la fonction de la
norme C, même si ce n'est pas bien, c'est courant.



Non seulement ça mais je crois que c'est interdit par la Norme.



Sans trop insister, avec un gcc sous Linux et MSVC, je n'ai pas pu
faire en sorte que strlen() soit appelée avec un simple printf() de
strlen("toto").

--
Pierre Maurette
Avatar
Eric Levenez
Le 13/07/09 04:07, dans <4a5a96f7$0$22890$,
« candide » a écrit :

Eric Levenez a écrit :




Oui. Un "const char" à la place des "char", c'est mieux.



Dit comme cela, je l'accepte volontiers.

Sinon, concernant le code que j'ai écrit, ok est une variable locale qui
renvoie
l'adresse d'un objet statique, donc ça ne pose pas de problème de retour. En
revanche celui-ci en pose :

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


comme me le confirme le compilateur alors que l'action est la même.



L'action n'est pas la même car là tu ne retournes pas l'adresse de la chaîne
constante, mais l'adresse d'une variable dans la pile. Ton code est
identique à :

int *h(void)
{
int ok = 42;
return &ok;
}

Et là il est clair qu'au retour de h, l'adresse ne sera plus valide.

Vous allez
peut-être me dire que l'adresse de "OK" n'est pas forcément la même que la
valeur de ok et donc que peut-être "OK" est recopié provisoirement.



Le problème ici ne vient pas d'OK mais de la durée d'allocation de "ok". Là
il faut mettre un static pour que la variable soit toujours présente après
le retour de h.

Oui. Un "const char" à la place du "char", c'est mieux.




OK mais je n'ai pas souvent vu cela (ce qui évidemment ne prouve rien ! ;)



C'est très courant.

Mais alors pourquoi le prototype de strchr() n'est-il pas :

const char *strchr(const char *s, int c);

au lieu de

char *strchr(const char *s, int c);



Tout ce qui concerne les chaînes est historique, et comme il n'y a qu'une
fonction dans la bibliothèque standard pour une action, que les chaînes
soient const ou non, il faut faire avec. Mais quand on écrit soit même une
fonction, on a la maîtrise de ce que l'on fait.

Là je ne vois pas ta logique. Dans les deux cas l'adresse de la chaîne est
utilisée (par une fonction dans ton premier exemple et par une variable dans
le second), donc il faut qu'elle soit allouée en mémoire.



Oui, j'aurais dû prendre sizeof au lieu de strlen. Je comprends que tu ne
comprennes pas ma logique mais ça reste troublant que "zozo" soit un objet qui
ait une adresse mémoire surtout si on n'a pas besoin de l'adresse (si c'est
jsute pour compter le nombre de caractères). Quand on écrit

int zB;

on ne se pose pas la question de savoir où la r-value 42 se trouve en mémoire.



Pour sizeof, effectivement là on peut se poser la question, mais dans tous
les cas, dès que l'on essaye de voir ce que le compilateur va générer comme
code, c'est que l'on fait des suppositions sur telle ou telle chose. Et un
jour ou l'autre ces suppositions seront fausses.

Si tu sous-entends que strlen("toto") doit être remplacé par 4 par le
compilateur, cela n'est pas évident car strlen peut être une fonction de
l'utilisateur qui fait tout autre chose que ce que fait la fonction de la
norme C, même si ce n'est pas bien, c'est courant.



Non seulement ça mais je crois que c'est interdit par la Norme.



Si l'on n'inclus pas "string.h" ou "strlib.h", je ne vois pas pourquoi on ne
pourrait avoir une fonction locale s'appelant strlen. Certains ici disent
que l'on ne doit pas définir de fonction commençant par "str", mais c'est
parfois les mêmes qui voulaient ajouter de nouvelles fonctions "str" non
normalisées pour contourner les problèmes avec certaines fonctions de la
bibliothèque standard (comme strcpy). Alors entre ce que l'on ne devrait pas
faire et ce que l'on fait tous les jours, il y a un monde.

--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Avatar
-ed-
On 13 juil, 04:07, candide wrote:
Sinon, concernant le code que j'ai écrit, ok est une variable locale qu i renvoie
l'adresse d'un objet statique, donc ça ne pose pas de problème de ret our. En
revanche celui-ci en pose :

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

}



Ouah, au bout de 3 ans de C, candide a découvert qu'on avait pas le
droit de retourner l'adresse d'une variable locale (enfin, on a
surtout pas le droit de l'utiliser...)


comme me le confirme le compilateur alors que l'action est la même.



Bah non. Dans le premier cas, tu retournes l'adresse d'une variable de
durée de vie permanente et dans ce dernier cas, celle d'une variable
dont la durée de vie s'interrompt précisément avec le return... C'est
nouveau ? Ou tu fais l'andouille pour voir si on est réveillés ?

OK mais je n'ai pas souvent vu cela (ce qui évidemment ne prouve rien  ! ;)  ).



Extrait de

http://www.bien-programmer.fr/clib/ed/src/buf.c
Module BUF:

/* macros
========================= ========================= ============ */

#define MODULE "BUF"
#define VER "1.5"
#define ID MODULE" Module "C" (c) ED 1999-2003"

/* constants
========================= ========================= ========= */
/* types
========================= ========================= ============= */
/* structures
========================= ========================= ======== */
/* private variables
========================= ========================= = */
/* private functions
========================= ========================= = */
/* entry points
========================= ========================= ====== */

/*
---------------------------------------------------------------------
BUF_sver()

---------------------------------------------------------------------
Role : Retourne une chaine "Version"

---------------------------------------------------------------------
E :
S : Pointeur de chaine ASCIIZ

---------------------------------------------------------------------
*/
const char *BUF_sver (void)
{
return VER;
}

/*
---------------------------------------------------------------------
BUF_sid()

---------------------------------------------------------------------
Role : Retourne une chaine "Identification"

---------------------------------------------------------------------
E :
S : Pointeur de chaine ASCIIZ

---------------------------------------------------------------------
*/
const char *BUF_sid (void)
{
return ID;
}


Mais alors pourquoi le prototype de strchr() n'est-il pas :

const char *strchr(const char *s, int c);

au lieu de

char *strchr(const char *s, int c);

?



Parce que rien n'oblige à ce que l'adresse retournée soit celle d'une
chaine non modifiable.C'est à l'utilisateur de savoir ce qu'il fait.
Le const du paramètre indique simplement que la fonction accepte
l'adresse d'une chaine non-modifiable parce que la fonction ne fait
aucun accès en écriture à cette chaine.

Ceci compile sans erreur et produit un comportement indéterminé.

char const *s = Hellon";

char *p = strchr(s, 'n');

if (p != NULL)
{
*p = 0;
}

Encore une fois, c'est la compétence du programmeur qui est en cause.
Si l'adresse passée est celle d'une chaine non modifiable, il faut
coder :

char const *s = Hellon";

char const *p = strchr(s, 'n');

if (p != NULL)
{
*p = 0; /* et la le compilateur detecte l'erreur */
}

Un compilateur fait ce qu'il peut, mais il ne peut pas voir toutes les
erreurs. Rien ne remplace le cerveau de l'homme pour le moment...

jsute pour compter le nombre de caractères). Quand on écrit

int zB;

on ne se pose pas la question de savoir où la r-value 42 se trouve en m émoire.



42 est un expression constante. Elle n'est pas en mémoire, elle n'a
pas d'adresse. (en réalité, elle est probablement intégrée à cert ains
opcodes résultants de la traduction en assembleur))
Avatar
candide
Eric Levenez a écrit :

L'action n'est pas la même car là tu ne retournes pas l'adresse de la chaîne
constante, mais l'adresse d'une variable dans la pile. Ton code est
identique à :

int *h(void)
{
int ok = 42;
return &ok;
}





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;
}




OK mais je n'ai pas souvent vu cela (ce qui évidemment ne prouve rien ! ;)



C'est très courant.




Je te fais confiance mais je n'ai pas trouvé d'exemples dans le code que je
consulte pour savoir comment on fait dans la vraie vie (set sans être dans la
vraie vie du programmeur). Si c'est courant, ça devrait être dans les livres
(rien dans Harbison & Steele et pas souvenir d'avoir vu ça dans K&R). Est-ce
dans la faq (je parle d'un retour style "OK" par une fonction de type const
char* sinon oui une déclaration du genre
const char *z="toto";
est courant.
)
Avatar
candide
Pierre Maurette a écrit :

char ok[]="OK";
est strictement équivalent à:
char ok[] = {'O', 'K', ''};
ou
char ok[3] = {'O', 'K', ''};




Oui, en effet, il y a "recopie", ah ! c'était pourtant élémentaire.

OK mais je n'ai pas souvent vu cela (ce qui évidemment ne prouve rien
! ;) ). Mais alors pourquoi le prototype de strchr() n'est-il pas :

const char *strchr(const char *s, int c);

au lieu de

char *strchr(const char *s, int c);

?



Parce que la fonction est prévue pour fonctionner sur des tableaux
modifiables. Un rechercher - remplacer par exemple. Le const indique que
la fonction ne modifiera pas s, et l'utilisateur sachant ce qu'il envoie
à la fonction fera ce que bon lui semble du retour (une copie de valeur
de pointeur), en particulier l'affectera à un char* ou un const char*.





Ah oui, bien sûr.
Avatar
candide
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 ;)
... le tout étant de savoir combien de temps ça va durer ... ;)
1 2 3 4 5