Frage

Ich bin ein wenig verwirrt über die Regeln in Bezug auf eingeschränkte Zeiger. jemand da draußen kann mir vielleicht helfen.

  1. Ist es legal, verschachtelt beschränkt Zeiger wie folgt zu definieren:

    int* restrict a;
    int* restrict b;
    
    
    a = malloc(sizeof(int));
    
    
    // b = a; <-- assignment here is illegal, needs to happen in child block
    // *b = rand();
    
    
    while(1)
    {
        b = a;  // Is this legal?  Assuming 'b' is not modified outside the while() block
        *b = rand();
    }
    
  2. Ist es legal, einen eingeschränkten Zeigerwert abzuleiten, wie folgt:

    int* restrict c;
    int* restrict d;
    
    
    c = malloc(sizeof(int*)*101);
    d = c;
    
    
    for(int i = 0; i < 100; i++)
    {
        *d = i;
        d++;
    }
    
    
    c = d; // c is now set to the 101 element, is this legal assuming d isn't accessed?
    *c = rand();
    

Danke! Andrew

War es hilfreich?

Lösung

Als Referenz ist hier die restrict Qualifikationsspiel eher Definition gewunden (von C99 6.7.3.1 "formale Definition beschränken"):

  

sein Sei D eine Erklärung eines gewöhnlichen   Bezeichner, stellt ein Mittel zur   Bezeichnen eines Objekts P als   beschränken qualifizierte Zeiger auf den Typ T.

     

Wenn D erscheint in einem Block und   nicht Speicherklasse haben   extern, lassen Sie B, um den Block zu bezeichnen. wenn D   erscheint in der Liste der Parameter   Erklärungen der Funktion   Definition, lassen B bezeichnen die   zugeordneten Block. Ansonsten lassen B   bezeichnen den Hauptblock (oder den Block   von was auch immer wird Funktion aufgerufen bei   Programmstart in einem freistehenden   Umwelt).

     

Im Folgenden eines Zeigers   Ausdruck E wird gesagt werden, basierend auf   Objekt P if (an einem gewissen Punkt Sequenz   in der Ausführung von B vor dem   Auswertung von E) P zum Punkt Modifizieren   auf eine Kopie des Arrays Objekt in   die darauf hingewiesen früher würde sich ändern   der Wert von E. Man beachte, dass „basiert“ ist   nur für Ausdrücke definiert mit   Zeigertypen.

     

Während jeder Ausführung von B sei L sein   jeder L-Wert, der & L hat auf Basis von P. Wenn   L wird verwendet, um den Wert des für den Zugriff auf   Objekt X dass es bezeichnet ist, und X   auch (durch ein beliebiges Mittel) modifiziert, dann wird die   gelten folgende Anforderungen: T wird   nicht const qualifiziert sein. jede andere   L-Wert verwendet, um den Wert von X zugreifen   wird auch seine Adresse hat, basierend auf   P. Jeder Zugriff dass X modifiziert wird   in Betracht gezogen wird auch P zu verändern,   Im Sinne dieses Subklausel. Wenn P   wird, um den Wert eines Zeigers zugewiesen   Ausdruck E die auf einem anderen basiert   eingeschränktes Zeigerobjekt P2,   mit dem Block B2 verbunden ist, dann entweder   wird die Ausführung von B2 beginnen, bevor   die Ausführung von B, oder   Ausführung von B2 wird vor Ende zu   die Zuordnung. Wenn diese   Anforderungen nicht erfüllt sind, dann wird die   Verhalten ist nicht definiert.

     

Hier ist eine Ausführung von B bedeutet, dass   Teil der Ausführung der   Programm, das auf dem entspräche   Lebensdauer eines Objekts mit Skalartyp   und eine automatische Lagerdauer   im Zusammenhang mit B.

Meine Lektüre der obigen Mittel, dass in Ihrer ersten Frage, a nicht b zugeordnet werden kann, sogar in einem „Kind“ Block - das Ergebnis ist nicht definiert. Ein solche Zuordnung vorgenommen werden könnte, wenn b in diesem ‚Unterblock‘ deklariert wurde, aber da b im gleichen Umfang wie a deklariert ist, kann die Zuordnung nicht vorgenommen werden.

Frage 2, die Zuordnungen zwischen c und d auch in undefiniertem Verhalten führen (in beiden Fällen).

Das entsprechende Bit aus dem Standard (für beiden Fragen) ist:

  

Wenn P den Wert von a zugeordnet ist,   Zeiger Ausdruck E, die auf basiert   ein anderes eingeschränktes Zeigerobjekt P2,   mit dem Block B2 verbunden ist, dann entweder   wird die Ausführung von B2 beginnen, bevor   die Ausführung von B, oder   Ausführung von B2 wird vor Ende zu   die Zuordnung.

Da die eingeschränkten Zeiger mit dem gleichen Block zugeordnet sind, ist es nicht möglich, für den Block B2 vor der Ausführung B, oder B2 zu beginnen vor der Übertragung zu beenden (da B und B2 ist der gleiche Block).

Der Standard gibt ein Beispiel, das diese ziemlich klar macht (ich glaube - die Klarheit der vier kurzen Absätzen des restrict Definition ist auf einer Stufe mit C ++ 's Namensauflösung Regeln):

  

Beispiel 4:

     

Die Regel Begrenzung Zuordnungen zwischen   eingeschränkter Zeiger nicht   unterscheiden zwischen einem Funktionsaufruf   und ein äquivalenter verschachtelter Block.   Mit einer Ausnahme nur   „Outer-zu-innen“ Zuordnungen zwischen   beschränkt Zeiger deklariert in verschachtelten   Blöcke Verhalten definiert.

{
    int * restrict p1;
    int * restrict q1;

    p1 = q1; //  undefined behavior

    {
        int * restrict p2 = p1; //  valid
        int * restrict q2 = q1; //  valid
        p1 = q2; //  undefined behavior
        p2 = q2; //  undefined behavior
    }
}

Andere Tipps

Der restrict Qualifier ist ein Hinweis an die Compiler, dass, wenn der Speicher durch die restrict qualifizierte Zeiger adressiert geändert wird, wird kein anderer Zeiger, die gleichen Speicher zugreifen. Der Compiler kann zu optimieren Code, auch wenn restrict qualifizierten Zeiger auf eine Weise wählen, die sonst zu falschem Verhalten führen könnten. Es ist die Verantwortung des Programmierers, um sicherzustellen, dass beschränken qualifizierte Zeiger verwendet werden, wie sie gemeint waren verwendet werden. Andernfalls kann ein unerwartetes Verhalten. ( link )

Wie Sie aus der obigen Beschreibung sehen können, sowohl Ihre Zuweisungen illegal sind, dass möglicherweise von einigen Compiler erzeugt in ausführbaren Dateien arbeiten, aber in anderen brechen. Erwarten Sie nicht, den Compiler selbst Fehler oder Warnungen zu emittieren als restrict nur eine Möglichkeit gibt, bestimmte Optimierung durchzuführen, die sie wählen können nicht ausführen, wie im Fall von volatile.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top