2014-09-10 17 views
5

ISO C99, tablice, które nie są jeszcze lwartościami rozpadają się wskaźniki i mogą być indeksowane, choć nie mogą być modyfikowane lub wykorzystane po następnym punkcie sekwencji. (source)tablice, które nie są lwartościami i punkty sekwencja restrykcyjne

Rozumiem, że ta funkcja umożliwia indeksowanie tablicy w przypadkach, gdy funkcja powrotu strukturę zawierającą tablicę, co jest niedozwolone w C89 (http://yarchive.net/comp/struct_return.html)

będziesz Proszę mi pomóc zrozumieć, dlaczego istnieje ograniczenie użycia/modyfikacji po następnym punkcie sekwencyjnym?

+1

Ok. Jestem przerażony. Gdzie w standardzie ISO C99 mówi dokładnie ten cytat, ponieważ nie mogę go nigdzie znaleźć. Jeśli masz zamiar zacytować standardy, opublikuj podsekcję iw razie potrzeby zaznacz punkt, z którego wyciągnąłeś cytat. – WhozCraig

+0

@MattMcNabb Do przodu p7, widzę twoje cytaty, nie PO (i nie spodziewali się, ponieważ jestem dokładnie obeznany z częstotliwością "zaniku" w standardzie). Dzięki za loc. (+1 w twojej odpowiedzi). – WhozCraig

+0

@WhozCraig zaktualizował moje odniesienia do w –

Odpowiedz

7

Uwaga, przytoczony tekst OP pochodzi z dokumentacji GCC. Istotne tekst od C99 do tworzenia kopii zapasowych, że cytat jest:

C99 6.5.2.2/5

Jeśli próbuje się zmodyfikować wynik wywołania funkcji lub do niej dostęp po następnym punkcie sekwencji , zachowanie jest niezdefiniowane.

a także z listy zmian w przedmowie:

zamiany tablicy na wskaźnik nie ogranicza się do lwartościami

nie mam tekst C89 do porównania, ale W opisie C99 konwersji między tablicą a wskaźnikiem (6.3.2.1/3) nie podano żadnych ograniczeń tablicy, która jest l-wartością. Również sekcja C99 dotycząca indeksowania (6.5.2.1/2) mówi o wyrażeniu będącym subskrybowanym jako po poprawnym wyrażeniu, nie wspomina też o wartościach l.


Rozważmy następujący kod:

struct foo 
{ 
    char buf[20]; 
}; 

struct foo foo(char const *p) { struct foo f; strcpy(f.buf, p); return f; } 

int main() 
{ 
    char *hello = foo("hello").buf; 
    char *bye = foo("bye").buf; 

    // other stuff... 

    printf("%s\n", hello); 
    printf("%s\n", bye); 
} 

Skąd wskaźniki hello i bye wskaż polecenie? Celem tej klauzuli jest powiedzenie, że kompilator nie musi przechowywać wszystkich zwróconych obiektów zawieszonych w pamięci, aby te wskaźniki pozostały ważne przez czas nieokreślony.

Zamiast tego, hello jest ważny tylko do następnego ; w tym przypadku (lub ogólnie do następnego punktu sekwencji). Pozostawia to kompilatorowi swobodę implementacji zwracających struktur przez wartość jako parametr ukrytego wskaźnika, jak opisuje Chris Torek w swoim doskonałym wpisie, który można "uwolnić" pod koniec bieżącego oświadczenia.

NB. Sytuacja C99 nie jest tak proste, jak to opisano w poście Chrisa, co ilustruje poniższy musi pracować:

printf("%s %s\n", foo("hello").buf, foo("bye").buf); 

Moja zainstalować gcc 4.8 wydaje się to dobrze chociaż - który współpracuje z -std=c99 i zwraca błąd z -std=c89 .

Powiązane problemy