2014-09-10 4 views
5

In ISO C99 zerfallen Arrays, die nicht lvales sind immer noch zu Zeigern und möglicherweise indiziert, obwohl sie nicht nach dem nächsten Sequenzpunkt geändert oder verwendet werden können. (source)Arrays, die nicht lvalues ​​und Sequenzpunkteinschränkung sind

Ich verstehe, dass diese Funktion Array-Indizierung in Fällen ermöglicht, wo eine Funktion, um eine Struktur, die ein Array zurückkehrt, die nicht in C89 erlaubt ist (http://yarchive.net/comp/struct_return.html)

werden Sie mir bitte helfen zu verstehen, warum es eine ist Einschränkung der Verwendung/Änderung nach dem nächsten Sequenzpunkt?

+1

Ok. Ich bin behindert. Wo im ISO C99-Standard heißt es genau dieses Zitat, da ich es nirgendwo finden kann. Wenn Sie die Standards zitieren, posten Sie bitte die Untersektion, und wenn nötig, Absatzmarke, woher Sie das Zitat gezogen haben. – WhozCraig

+0

@MattMcNabb Weiterleiten p7, sehe ich Ihre Zitation, nicht die OP's (und nicht erwartet, wie ich bin vertraut mit der Häufigkeit von "Verfall" im Standard). Danke für die Lok. (+1 auf deine Antwort). – WhozCraig

+0

@WhozCraig hat meine Referenzen aktualisiert –

Antwort

7

Hinweis: Der zitierte Text OP stammt aus der GCC-Dokumentation. Relevante Text von C99 dieses Zitat zu sichern ist:

C99 6.5.2.2/5

Wenn versucht wird, das Ergebnis eines Funktionsaufruf zu ändern oder es nach dem nächsten Sequenzpunkt für den Zugriff auf , das Verhalten ist nicht definiert.

und auch aus der Liste der Änderungen im Vorwort:

Umwandlung von Array-Zeiger nicht darauf beschränkt,

ich den C89 Text nicht Lvalues ​​habe zu vergleichen, aber Die C99-Beschreibung der Zeiger-zu-Zeiger-Umwandlung (6.3.2.1/3) erwähnt keine Einschränkung für das Feld, das ein L-Wert ist. Der C99-Abschnitt über Subskribierung (6.5.2.1/2) spricht auch davon, dass der Ausdruck als Postfix-Ausdruck indiziert ist, und erwähnt auch keine lvales.


diesen Code vor:

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

Wo kommen die Zeiger hello und bye Punkt? Der Zweck dieser Klausel besteht darin, zu sagen, dass der Compiler nicht alle zurückgegebenen Objekte irgendwo im Speicher herumhängen lassen muss, damit diese Zeiger unbegrenzt gültig bleiben.

Stattdessen ist die hello nur gültig bis zur nächsten ; in diesem Fall (oder nächsten Sequenzpunkt im Allgemeinen). Dadurch kann der Compiler die zurückgegebenen Strukturen nach Wert als versteckten Zeigerparameter implementieren, wie Chris Torek in seinem ausgezeichneten Beitrag beschreibt, der am Ende der aktuellen Anweisung "freigegeben" werden kann.

NB. Die C99 Situation ist nicht ganz so einfach, wie in Chris Beitrag beschrieben, wie die folgenden hat zu arbeiten:

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

Mein von gcc installiert 4.8 scheint es richtig, obwohl - das mit -std=c99 funktioniert und segfaults mit -std=c89 .

Verwandte Themen