Doppelzeiger-Const-Korrektheitswarnungen in C

Lesezeit: 4 Minuten

Benutzeravatar von Michael Koval
Michael Kowal

Ein Zeiger auf nicht konstante Daten kann implizit in einen Zeiger auf konstante Daten desselben Typs konvertiert werden:

int       *x = NULL;
int const *y = x;

Das Hinzufügen zusätzlicher konstanter Qualifizierer, die der zusätzlichen Indirektion entsprechen, sollte logischerweise auf die gleiche Weise funktionieren:

int       *      *x = NULL;
int       *const *y = x; /* okay */
int const *const *z = y; /* warning */

Kompilieren Sie dies mit GCC oder mit dem Clang -Wall flag führt jedoch zu folgender Warnung:

test.c:4:23: warning: initializing 'int const *const *' with an expression of type
      'int *const *' discards qualifiers in nested pointer types
    int const *const *z = y; /* warning */
                      ^   ~

Warum fügt man eine zusätzliche hinzu const Qualifizierer “Qualifizierer in verschachtelten Zeigertypen verwerfen”?

  • Kleine Anmerkung zur Terminologie: Ein Cast ist eine explizite Konvertierung. Was Sie hier tun, ist eine implizite Konvertierung, keine Umwandlung.

    – Tim Martin

    20. Februar 2011 um 6:46 Uhr

  • ITYM-Zeiger auf const Zeiger auf const („const-Zeiger“ kann mehrdeutig sein). Wenn x -> y -> z (wo -> bedeutet nur “zeigt auf” und nicht den Dereferenzierungsoperator), können Sie den Inhalt ändern z ohne Veränderung y. Wenn es sich also um einen Zeiger auf eine Konstante oder einen Zeiger auf eine Nicht-Konstante handelt, können Sie den Wert ändern z ohne Veränderung y.

    – Tim Martin

    20. Februar 2011 um 7:05 Uhr

  • Ist dies nicht nur ein Beispiel dessen, was in den C++-FAQs erklärt wird const Korrektheit?

    – Jeff Mercado

    20. Februar 2011 um 7:07 Uhr

  • @Jeff Die FAQ besagt, dass es in Ordnung ist, zu casten Foo ** zu Foo const * const *. Ich verstehe nicht ganz, wie das hier nicht zutrifft. Aber es klingt so, als wäre dies relevant. Wenn Sie es als Antwort posten möchten, erhalten Sie meine Stimme.

    – Tim Martin

    20. Februar 2011 um 7:11 Uhr

  • @Jeff M: Die C- und C++-Regeln zur Konstantenkorrektheit sind unterschiedlich, und diese Frage bezieht sich auf C.

    – Café

    20. Februar 2011 um 7:21 Uhr

Benutzeravatar von caf
Café

Der Grund warum const kann nur eine Ebene tiefer hinzugefügt werden, ist subtil und wird durch erklärt Frage 11.10 in der comp.lang.c-FAQ.

Betrachten Sie kurz dieses Beispiel, das eng mit Ihrem verwandt ist:

const int i;
int *p;
int const **z = &p;
*z = &i;
/* Now p points to i */

C vermeidet dieses Problem, indem es Zuweisungen nur erlaubt, Qualifizierer auf der ersten Ebene, auf die gezeigt wird, zu verwerfen (also die Zuweisung an z hier ist nicht erlaubt).

Ihr genaues Beispiel leidet nicht unter diesem Problem, weil die const die zweite Ebene bedeutet, dass die Zuordnung zu *z wäre ohnehin nicht erlaubt. C++ möchten erlauben es in genau diesem Fall, aber die einfacheren Regeln von C unterscheiden nicht zwischen Ihrem Fall und dem obigen Beispiel.

  • @caf- Ich habe mich gefragt, warum dies eine Warnung generiert! Vermutlich erlauben die C++-Regeln diese Umwandlung tatsächlich.

    – Vorlagentypdef

    20. Februar 2011 um 7:28 Uhr

  • Danke für den informativen Link. Habe ich bisher nur ausgiebig genutzt const in C++, daher ist dieser Unterschied im Verhalten ziemlich überraschend.

    – Michael Koval

    20. Februar 2011 um 7:29 Uhr

  • Der Link ist jetzt kaputt.

    – Martinkunew

    7. Juni 2019 um 10:38 Uhr

Der durch die andere Antwort verlinkte FAQ-Eintrag erklärt, warum folgender Code nicht erlaubt ist:

int **x = whatever;
const int **z = x;

Allerdings dein Code const int *const *z = x; ist ganz anders, und es leidet nicht unter dem gleichen Fehler, der von den FAQ angesprochen wird.

Tatsächlich ist an letzterem Code konzeptionell nichts auszusetzen. Es ist nur ein Fehler in der C-Spezifikation, dass es nicht erlaubt ist, und es zwingt C-Programmierer, hässliche Umwandlungen in ihren Code aufzunehmen.

Es wäre C möglich gewesen, die gleichen Regeln wie C++ zu verwenden; Das C-Normenkomitee hat sich jedoch nicht dazu entschlossen.

Der Grund, warum der Automatismus des Hinzufügens von Qualifizierern nur für die 1. Indirektionsebene funktioniert, kann der Norm entnommen werden:

Der Standard Ansprüche in 6.5.16.1 für eine Abtretung, dass “Beide Operanden sind Zeiger auf qualifizierte oder nicht qualifizierte Versionen kompatibler Typen, und der Typ, auf den links gezeigt wird, hat alle Qualifizierer des Typs, auf den rechts gezeigt wird
Der letzte Teil des Satzes bedeutet, dass das Hinzufügen eines Qualifizierers zum Typ, auf den gezeigt wird, kein Problem ist.
Und der erste Teil behauptet “kompatible” Typen. Und (glaube ich) 6.7.3 (11) beschreibt dies für qualifizierte Typen: “Damit zwei qualifizierte Typen kompatibel sind, müssen beide die identisch qualifizierte Version eines kompatiblen Typs haben.

Wenn Sie dies lesen, werden Ihre Typen, auf die gezeigt wird, nicht als kompatibel betrachtet (selbst wenn es möglich wäre, einen dem anderen zuzuordnen).

Daher würde ich sagen, dass die klirrende Warnung über wegwerfen qualifiers ist etwas irreführend, bezieht sich aber auf die nicht identisch qualifizierten Typen, auf die gezeigt wird.

1414430cookie-checkDoppelzeiger-Const-Korrektheitswarnungen in C

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy