31 Stimmen

typedef Zeiger const weirdness

Beachten Sie bitte den folgenden Code:

typedef struct Person* PersonRef;
struct Person {
  int age;
};

const PersonRef person = NULL;

void changePerson(PersonRef newPerson) {
  person = newPerson;
}

Aus irgendeinem Grund beschwert sich der Compiler, dass der Nur-Lese-Wert nicht zugewiesen werden kann. Aber die const Schlüsselwort sollte den Zeiger nicht konstant machen. Irgendwelche Ideen?

51voto

Piotr Praszmo Punkte 17533

Beachten Sie, dass

typedef int* intptr;
const intptr x;

ist nicht dasselbe wie:

const int* x;

intptr ist Zeiger auf int. const intptr ist ein konstanter Zeiger auf int , nicht Zeiger auf Konstante int .

so, nach einem typedef Zeiger, ich kann nicht machen es const auf den Inhalt mehr?

Es gibt einige hässliche Wege, wie zum Beispiel gcc's Typof-Makro :

typedef int* intptr;
intptr dummy;
const typeof(*dummy) *x;

aber, wie Sie sehen, ist es sinnlos, wenn Sie den Typ dahinter kennen intptr .

13voto

Jens Gustedt Punkte 74457
const PersonRef person = NULL;

est

struct Person*const person= NULL;

Sie konstatieren also den Zeiger und nicht das Objekt.

8voto

Zappotek Punkte 325

Das Problem ist zwar durch die obigen Antworten bereits gelöst, aber ich vermisse den Grund dafür...

Also vielleicht als Faustregel:

  1. Le site const bezieht sich immer auf sein Vorgänger-Token.
  2. Falls es keine solche gibt, "konstituiert" sie stattdessen ihre Nachfolgemarke.

Diese Regel kann Ihnen wirklich helfen, wenn Sie einen Zeiger auf const-Zeiger oder etwas ähnlich Ordentliches deklarieren.

In Anbetracht dessen sollte klar werden, warum

struct Person *const person = NULL;

erklärt eine konstanter Zeiger zu einer veränderbaren Struktur.

Denken Sie darüber nach, dass Ihr typedef "Gruppen" die struct Person mit dem Zeiger-Token * . Also, zum Schreiben

const PersonRef person = NULL;

sieht Ihr Compiler etwa so aus (Pseudocode):

const [struct Person *]person = NULL;

Da es nichts zu tun gibt const links, deklariert es die Spielmarke rechts davon struct Person * の定数です。

Nun, ich denke, das ist der Grund, warum ich es nicht mag, Zeiger durch Typendefinitionen zu verstecken, während ich Typendefinitionen als solche sehr wohl mag. Was ist mit dem Schreiben von

typedef struct Person { ... } Person;
const Person *person; /*< const person */
Person *const pointer; /*< const pointer to mutable person */

und es sollte für Compiler und Menschen ziemlich klar sein, was Sie vorhaben.

4voto

Lundin Punkte 171916

Verstecken Sie niemals Zeiger hinter Typedefs, das ist eine wirklich schlechte Praxis und führt nur zu Fehlern.

Ein solcher berüchtigter Fehler ist, dass ein typedef:ed-Zeigertyp, der als const deklariert ist, als "konstanter Zeiger auf nicht-konstante Daten" behandelt wird, anstatt als "nicht-konstanter Zeiger auf konstante Daten", was man intuitiv erwartet. Das ist es, was in Ihrem Programm passiert.


Lösung:

typedef struct
{
  int age;
} Person;

const Person* person = NULL; // non-constant pointer to constant Person

0voto

Jeegar Patel Punkte 24720

Sie erhalten eine Fehlermeldung

error: assignment of read-only variable ‘person’

zur Erklärung

person = newPerson;

weil Sie person als const deklariert haben, so dass sein Wert nur lesbar ist .... Konstanter Wert kann nicht geändert werden

Wenn Sie diese Variable ändern wollen, warum halten Sie sie dann zurück?

Entfernen Sie das Schlüsselwort const, dann funktioniert Ihr Code einwandfrei.

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