Ich stieß auf einen verwirrenden Fall, als ich eine semantische Analyse für meinen Compilerkurs durchführte.Kein konstantes Initialisierungselement?
GCC sagt "Fehler: Initialisierungselement ist nicht konstant" für die Variable "a".
Warum?
Ich stieß auf einen verwirrenden Fall, als ich eine semantische Analyse für meinen Compilerkurs durchführte.Kein konstantes Initialisierungselement?
GCC sagt "Fehler: Initialisierungselement ist nicht konstant" für die Variable "a".
Warum?
Die Sprache C erfordert Initialisierer für globale Variablen als konstante Ausdrücke. Die Motivation dahinter ist, dass der Compiler den Ausdruck zur Kompilierzeit berechnen und den berechneten Wert in die generierte Objektdatei schreiben kann.
The C standard bietet spezifische Regeln für das, was ist ein konstanter Ausdruck:
- An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants,
sizeof
expressions whose results are integer constants,_Alignof
expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to thesizeof
or_Alignof
operator .- More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:
- an arithmetic constant expression,
- a null pointer constant,
- an address constant, or
- an address constant for a complete object type plus or minus an integer constant expression.
Wie Sie nicht der Fälle umfassen ein Array Zugriffsausdruck oder einen Pointer-Dereference sehen können. So qualifiziert sich "abcd"[2]
nicht als konstanter Ausdruck pro Standard.
Nun ist der Standard sagt auch:
- An implementation may accept other forms of constant expressions.
So wäre es nicht der Standard verletzt "abcd"[1]
als konstanten Ausdruck zu ermöglichen, aber es ist auch nicht erlaubt werden garantiert.
Es liegt also an Ihnen, ob Sie es in Ihrem Compiler erlauben. Es wird in beiden Fällen standardkonform sein (obwohl es mehr Arbeit zulässt, da Sie in Ihrer isConstantExpression
Prüfung einen weiteren Fall benötigen und Sie den Ausdruck tatsächlich zur Kompilierzeit auswerten müssen, also werde ich ihn ablehnen).
int a = "abcd" [2];
a ist eine globale Variable, die zur Kompilierzeit initialisiert wird, aber "abcd" [2] wird zur Laufzeit berechnet.
char b = "abcd" [2];
Hier ist b eine lokale Variable und es wird zur Laufzeit nach "abcd" [2] berechnet.
Sieht aus wie eine GCC-Eigenart - [clang ist ziemlich glücklich damit] (https://godbolt.org/g/0CPrpX), und das ist auch [Intels ICC] (https://godbolt.org/g/JGL3nL). –
@PaulR Wenn man sich die Assembly anschaut, behandelt clang sie nicht als konstanten Ausdruck (der Wert wird am Anfang von main berechnet und dann in der Variablen gespeichert). Es sieht also so aus, als ob clang die Anforderung des Standards fallen lässt, dass globale Initialisierer statisch sein müssen. – sepp2k
kompiliert für mich in vs und gedruckt 99 c –