Oui, la durée de vie d'une variable locale est dans la portée({
,}
) dans laquelle elle est créée.
Les variables locales ont un stockage automatique ou local. Automatique car elles sont automatiquement détruites une fois que la portée dans laquelle elles sont créées se termine.
Cependant, Ce que vous avez ici est une chaîne littérale, qui est allouée dans une mémoire en lecture seule définie par l'implémentation. Les chaînes littérales sont différentes des variables locales et restent en vie tout au long de la durée du programme. Elles ont une durée de vie statique [Réf 1].
Un avertissement!
Cependant, notez que toute tentative de modifier le contenu d'une chaîne littérale est un comportement indéfini (CI). Les programmes utilisateur ne sont pas autorisés à modifier le contenu d'une chaîne littérale.
Il est donc toujours conseillé d'utiliser un const
lors de la déclaration d'une chaîne littérale.
const char*p = "chaine";
au lieu de,
char*p = "chaine";
En fait, en C++, il est déconseillé de déclarer une chaîne littérale sans le const
bien que ce ne soit pas le cas en C. Cependant, déclarer une chaîne littérale avec un const
vous donne l'avantage que les compilateurs vous donneraient généralement un avertissement en cas de tentative de modifier la chaîne littérale dans le deuxième cas.
Programme d'exemple:
#include
int main()
{
char *str1 = "chaine littérale";
const char *str2 = "chaine littérale";
char source[]="Chaine d'exemple";
strcpy(str1,source); // Pas d'avertissement ou d'erreur juste un Comportement Indéfini
strcpy(str2,source); // Le compilateur émet un avertissement
return 0;
}
Sortie:
cc1: les avertissements sont traités comme des erreurs
prog.c: Dans la fonction 'main':
prog.c:9: erreur: le passage de l'argument 1 de 'strcpy' ignore les qualificateurs du type cible du pointeur
Remarquez que le compilateur avertit pour le deuxième cas, mais pas pour le premier.
Pour répondre à la question posée par quelques utilisateurs ici:
Qu'en est-il des littéraux intégraux?
En d'autres termes, le code suivant est-il valide?
int *foo()
{
return &(2);
}
La réponse est non, ce code n'est pas valide. Il est mal formé et provoquera une erreur du compilateur.
Quelque chose comme:
prog.c:3: erreur: une l-value est requise comme opérande «&» unaire
Les chaînes littérales sont des l-value, c'est-à-dire: Vous pouvez prendre l'adresse d'une chaîne littérale, mais ne pouvez pas changer son contenu.
Cependant, tout autre littéral (int
, float
, char
, etc.) sont des r-values (le standard C utilise le terme la valeur d'une expression pour ceux-ci) et leur adresse ne peut être prise du tout.
[Réf 1]Standard C99 6.4.5/5 "Chaînes littérales - Sémantique":
Dans la phase de traduction 7, un octet ou un code de valeur zéro est ajouté à chaque séquence de caractères multioctets qui résulte d'une ou de plusieurs chaînes littérales. La séquence de caractères multioctets est ensuite utilisée pour initialiser un tableau de durée de stockage statique et de longueur juste suffisante pour contenir la séquence. Pour les littéraux de chaîne de caractères, les éléments du tableau ont le type char, et sont initialisés avec les octets individuels de la séquence de caractères multioctets; pour les littéraux de chaîne large, les éléments du tableau ont le type wchar_t, et sont initialisés avec la séquence des caractères larges...
Il n'est pas spécifié si ces tableaux sont distincts tant que leurs éléments ont les valeurs appropriées. Si le programme tente de modifier un tel tableau, le comportement est indéfini.
13 votes
La seule "var" que vous avez dans votre fonction est le paramètre
int rc
. Sa durée de vie se termine à chacun desreturn
. Les pointeurs que vous renvoyez sont à des littéraux de chaîne. Les littéraux de chaîne ont une durée de stockage statique : leur durée de vie est au moins aussi longue que celle du programme.0 votes
Que se passe-t-il si ce n'est pas une chaîne littérale mais d'autres types de littéraux, tels que : int *foo() { return &(2); // ou // int n = 2; // return &n; }
0 votes
Vérifiez la modification dans ma réponse qui répond à votre question. Notez que vous auriez dû poster cela en tant que commentaire et non en tant que réponse. Les questions, les doutes, etc. devraient être posés dans les commentaires, seules les réponses devraient être postées sous forme de réponses.
0 votes
Qu'entendez-vous par "valide"? Votre code fonctionnera sûrement (et vous pouvez le voir si vous essayez de le compiler), cependant je ne peux pas imaginer une utilisation pour une fonction qui renvoie une chaîne constante.
14 votes
@PedroAlves Pourquoi pas? Les méthodes permettent l'abstraction; et si dans le futur la chaîne de caractères est lue à partir d'une ressource de traduction, mais que le support de l'internationalisation n'est pas nécessaire pour la V1 (ou la V0.5) d'un produit?
0 votes
@dlev Bien sûr, mais cette méthode ne lit pas la chaîne de nulle part, elle retourne simplement une chaîne constante. Cette question peut être remplacée par "Est-ce qu'une méthode peut retourner une chaîne constante?" ou "Comment puis-je retourner une chaîne constante à partir d'une méthode?".
1 votes
@PedroAlves "Votre code fonctionnera certainement (et vous pouvez le voir si vous essayez de le compiler)," Ce n'est pas le cas. De nombreux (la plupart? Essentiellement tous?) compilateurs C accepteront du code illégal et émettront souvent du code qui semble fonctionner. Mais essayez-le dans un autre compilateur (ou même une version différente du même compilateur) et il pourrait planter.
6 votes
@PedroAlves, une fonction qui renvoie une seule chaîne constante pourrait avoir une utilité limitée, mais que diriez-vous d'une fonction qui renvoie l'une quelconque d'un certain nombre de chaînes constantes en fonction de l'entrée ou de l'état de l'objet? Un exemple simple serait une fonction pour convertir une énumération en sa représentation sous forme de chaîne.
5 votes
Vous n'avez clairement jamais vu la fonction
strerror
.0 votes
Vous voudrez peut-être utiliser un
char const * const foo()
car il correspond parfaitement au type de votre pointeur.