2017-03-28 1 views
6

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?

+2

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). –

+1

@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

+0

kompiliert für mich in vs und gedruckt 99 c –

Antwort

5

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:

  1. 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 the sizeof or _Alignof operator .
  2. 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:

  1. 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).

0

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.

Verwandte Themen