Tak, czas życia zmiennej lokalnej mieści się w zakresie ( {
, }
), w którym została utworzona.
Zmienne lokalne mają pamięć automatyczną lub lokalną. Automatyczne, ponieważ są automatycznie niszczone po zakończeniu zakresu, w którym zostały utworzone.
Jednak mamy tutaj literał łańcuchowy, który jest przydzielony w implementacji pamięci tylko do odczytu. Literały łańcuchowe różnią się od zmiennych lokalnych i pozostają żywe przez cały okres istnienia programu. Mają statyczny czas trwania [Ref 1] żywotność.
Słowo ostrzeżenia!
Należy jednak pamiętać, że każda próba zmodyfikowania zawartości literału ciągu jest niezdefiniowanym zachowaniem (UB). Programy użytkownika nie mogą modyfikować zawartości literału ciągu.
W związku z tym zawsze zaleca się użycie const
while deklarując literał ciągu.
const char*p = "string";
zamiast,
char*p = "string";
W rzeczywistości w C ++ deklarowanie literału tekstowego bez const
chociaż nie w C.Jednakże zadeklarowanie literału ciągu znaków za pomocą a const
daje ci tę zaletę, że kompilatory zwykle dają ostrzeżenie w przypadku próby zmodyfikowania literału ciągu w drugi przypadek.
Przykładowy program :
#include<string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[]="Sample string";
strcpy(str1,source);
strcpy(str2,source);
return 0;
}
Wynik:
cc1: ostrzeżenia traktowane jako błędy
prog.c: W funkcji „main”:
prog.c: 9: error: przekazanie argumentu 1 z „strcpy” usuwa kwalifikatory z typu docelowego wskaźnika
Zwróć uwagę, że kompilator ostrzega przed drugim przypadkiem, ale nie w pierwszym.
Aby odpowiedzieć na pytanie zadane przez kilku użytkowników:
O co chodzi z literałami całkowitymi?
Innymi słowy, czy poniższy kod jest prawidłowy?
int *foo()
{
return &(2);
}
Odpowiedź brzmi: nie, ten kod jest nieprawidłowy. Jest źle sformułowany i spowoduje błąd kompilatora.
Coś jak:
prog.c:3: error: lvalue required as unary ‘&’ operand
Literały łańcuchowe są l-wartościami, tj .: Możesz wziąć adres literału ciągu, ale nie możesz zmienić jego zawartości.
Jednak inne literałami ( int
, float
, char
, etc.) są wartości R (średnia C używa określenia wartości wyrażenia dla nich) i ich adres nie może być wykorzystany w ogóle.
[Ref 1] C99 standard 6.4.5 / 5 "Literały łańcuchowe - semantyka":
W fazie translacji 7, bajt lub kod o wartości zero jest dołączany do każdej wielobajtowej sekwencji znaków, która wynika z literału ciągu lub literałów. Sekwencja znaków wielobajtowych jest następnie używana do zainicjowania tablicy o statycznym czasie trwania i długości wystarczającej do zawarcia sekwencji . W przypadku literałów łańcuchów znaków elementy tablicy mają typ char i są inicjowane pojedynczymi bajtami wielobajtowej sekwencji znaków; w przypadku literałów szerokich ciągów elementy tablicy mają typ wchar_t i są inicjowane sekwencją szerokich znaków ...
Nie jest określone, czy te tablice są różne, pod warunkiem, że ich elementy mają odpowiednie wartości. Jeśli program spróbuje zmodyfikować taką tablicę, zachowanie jest niezdefiniowane .
int rc
. Jego żywotność kończy się na każdym zreturn
-s. Wskaźniki, które zwracasz, dotyczą literałów łańcuchowych. Literały łańcuchowe mają statyczny czas trwania: ich żywotność jest co najmniej tak długa, jak czas trwania programu.