476 Stimmen

Wie viele Ebenen von Zeigern können wir haben?

Wie viele Zeiger ( * ) in einer einzigen Variablen erlaubt sind?

Betrachten wir das folgende Beispiel.

int a = 10;
int *p = &a;

In ähnlicher Weise können wir haben

int **q = &p;
int ***r = &q;

und so weiter.

Zum Beispiel,

int ****************zz;

418voto

P.P Punkte 111806

En C Norm legt die Untergrenze fest:

5.2.4.1 Übersetzungsgrenzen

276 Die Implementierung muss in der Lage sein, mindestens ein Programm zu übersetzen und auszuführen, das mindestens eine Instanz jeder der folgenden Grenzen enthält: [...]

279 - 12 Zeiger-, Array- und Funktionsdeklaratoren (in beliebigen Kombinationen), die eine Arithmetik-, Struktur-, Union- oder void-Typ in einer Deklaration

Die Obergrenze ist implementierungsspezifisch.

164voto

Kaz Punkte 51547

In C-Programmen wird in der Regel eine unendliche Zeigerumleitung verwendet. Eine oder zwei statische Ebenen sind üblich. Dreifache Indirektion ist selten. Aber unendliche Indirektion ist sehr häufig.

Die unendliche Zeigerumleitung wird natürlich mit Hilfe einer Struktur erreicht, nicht mit einem direkten Deklarator, was unmöglich wäre. Und ein struct wird benötigt, damit man auf den verschiedenen Ebenen, auf denen es enden kann, andere Daten in diese Struktur aufnehmen kann.

struct list { struct list *next; ... };

jetzt können Sie list->next->next->next->...->next . Es handelt sich eigentlich nur um mehrere Zeigerumleitungen: *(*(..(*(*(*list).next).next).next...).next).next . Und die .next ist im Grunde ein Noop, wenn es das erste Glied der Struktur ist, also können wir uns das so vorstellen ***..***ptr .

Hierfür gibt es eigentlich keine Grenzen, da die Links mit einer Schleife durchlaufen werden können, anstatt mit einem riesigen Ausdruck wie diesem, und außerdem kann die Struktur leicht kreisförmig gestaltet werden.

Mit anderen Worten, verknüpfte Listen sind das ultimative Beispiel für das Hinzufügen einer weiteren Ebene der Indirektion, um ein Problem zu lösen, da man dies dynamisch mit jeder Push-Operation macht. :)

84voto

Alok Save Punkte 196241

Theoretisch:

Sie können so viele Ebenen von Umleitungen haben, wie Sie wollen.

Praktisch:

Natürlich kann nichts, was Speicher verbraucht, unbegrenzt sein, sondern es gibt Beschränkungen aufgrund der verfügbaren Ressourcen der Hostumgebung. Praktisch gibt es also eine Obergrenze für das, was eine Implementierung unterstützen kann, und die Implementierung muss dies entsprechend dokumentieren. Bei all diesen Artefakten gibt die Norm also nicht die Obergrenze an, wohl aber die Untergrenzen.

Hier ist die Referenz:

C99 Standard 5.2.4.1 Übersetzungsgrenzen:

- 12 Zeiger-, Array- und Funktionsdeklaratoren (in beliebigen Kombinationen), die eine Arithmetik-, Struktur-, Union- oder void-Typ in einer Deklaration.

Dies gibt die Untergrenze an, die jede Implementierung muss Unterstützung. In einer Fußnote heißt es in der Norm weiter:

18) Implementierungen sollten nach Möglichkeit keine festen Übersetzungsgrenzen vorgeben.

80voto

BoBTFish Punkte 18837

Wie bereits gesagt wurde, gibt es "theoretisch" keine Einschränkungen. Aus Interesse habe ich dies jedoch mit g++ 4.1.2 ausgeführt, und es funktionierte mit einer Größe von bis zu 20.000. Kompilieren war allerdings ziemlich langsam, also habe ich es nicht mit höheren Werten versucht. Ich würde also vermuten, dass g++ auch keine Begrenzung auferlegt. (Versuchen Sie die Einstellung size = 10 und in ptr.cpp nachsehen, wenn es nicht sofort offensichtlich ist).

g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr

create.cpp

#include <iostream>

int main()
{
    const int size = 200;
    std::cout << "#include <iostream>\n\n";
    std::cout << "int main()\n{\n";
    std::cout << "    int i0 = " << size << ";";
    for (int i = 1; i < size; ++i)
    {
        std::cout << "    int ";
        for (int j = 0; j < i; ++j) std::cout << "*";
        std::cout << " i" << i << " = &i" << i-1 << ";\n";
    }
    std::cout << "    std::cout << ";
    for (int i = 1; i < size; ++i) std::cout << "*";
    std::cout << "i" << size-1 << " << \"\\n\";\n";
    std::cout << "    return 0;\n}\n";
    return 0;
}

64voto

mihai Punkte 35227

Hört sich nach Spaß an.

  • Visual Studio 2010 (unter Windows 7), können Sie 1011 Ebenen haben, bevor Sie diesen Fehler erhalten:

    fataler Fehler C1026: Stapelüberlauf des Parsers, Programm zu komplex

  • gcc (Ubuntu), 100k+ * ohne einen Absturz! Ich denke, die Hardware ist hier die Grenze.

(nur mit einer Variablenerklärung getestet)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X