C definiert mindestens 3 Ebenen des "konstanten Ausdrucks":
6.6 Absatz 3 lautet:
Konstante Ausdrücke dürfen keine Zuweisung, Inkrementierung, Dekrementierung, Funktionsaufruf, oder Kommaoperatoren, außer wenn sie in einem Teilausdruck enthalten sind, der nicht enthalten ist ausgewertet.
Also bedeutet das 1,2
ist kein konstanter Ausdruck?
In Absatz 8 heißt es:
Ein arithmetischer Konstantenausdruck soll einen arithmetischen Typ haben und nur haben Operanden, die Integer-Konstanten, Floating-Konstanten, Enumerationskonstanten, Zeichen sind Konstanten und Größe von Ausdrücken. Übergibt Operatoren in einem arithmetischen Konstantenausdruck darf nur arithmetische Typen in arithmetische Typen umwandeln, außer als Teil eines Operanden in a sizeof-Operator, dessen Ergebnis eine Ganzzahlkonstante ist.
Was sind die Operanden in (union { uint32_t i; float f; }){ 1 }.f
? Wenn 1
der Operand ist, dann ist dies vermutlich ein arithmetischer Konstantenausdruck, aber wenn { 1 }
der Operand ist, dann ist es eindeutig nicht.
Bearbeiten: Eine weitere interessante Beobachtung: 7.17 Absatz 3 erfordert, dass das Ergebnis von offsetof
ein ganzzahliger konstanter Ausdruck vom Typ size_t
ist, aber die Standardimplementierungen von offsetof
, soweit Ich kann sagen, dass keine konstanten Integer-Ausdrücke nach dem Standard sein müssen. Dies ist natürlich in Ordnung, da eine Implementierung (unter 6.6 Absatz 10) erlaubt ist, andere Formen von konstanten Ausdrücken zu akzeptieren, oder das offsetof
-Makro als __builtin_offsetof
anstatt über die Zeiger-Subtraktion implementiert. Der Kern dieser Beobachtung ist jedoch, dass Sie, wenn Sie offsetof
in einem Kontext verwenden möchten, in dem ein ganzzahliger konstanter Ausdruck benötigt wird, wirklich das von der Implementierung bereitgestellte Makro verwenden und nicht Ihr eigenes rollen müssen.
Basierend auf Ihrer Lektüre ist 1,2
kein konstanter Ausdruck. Ich weiß nicht, warum es nicht ist, nur dass ich mit dir übereinstimme, dass es nicht ist (trotz der Tatsache, dass es wahrscheinlich sein sollte).
6.5.2 spezifiziert zusammengesetzte Literale als Postfixoperator. Also in
%Vor% Die Operanden sind (union { uint32_t i; float f; }){ 1 }
und f
für den Operator .
. Es ist kein arithmetischer Konstantenausdruck, da das erste Argument ein union
-Typ ist, aber ein konstanter Ausdruck.
UPDATE: Ich habe dies auf eine andere Interpretation des Standards gestützt.
Meine vorherige Argumentation war, dass (union { uint32_t i; float f; }){ 1 }.f
die Kriterien für einen konstanten Ausdruck erfüllte und daher ein konstanter Ausdruck war. Ich denke immer noch, dass es die Kriterien für einen konstanten Ausdruck (6.6 Absatz 3) erfüllt, aber dass es keine der Standardtypen von konstanten Ausdrücken (Ganzzahl, Arithmetik oder Adresse) ist und daher nur von 6.6 Absatz als konstanter Ausdruck abhängig ist 10, die implementierungsdefinierte konstante Ausdrücke erlaubt.
Ich wollte auch zu deinem Schnitt kommen. Ich wollte argumentieren, dass die "Hack" -Implementierung von offsetof
ein konstanter Ausdruck war, aber ich denke, es ist das gleiche wie oben: Es erfüllt die Kriterien für einen konstanten Ausdruck (und möglicherweise eine Adresskonstante), ist aber keine Ganzzahlkonstante Ausdruck und ist daher außerhalb von Absatz 6.6 ungültig.
Wenn 1,2
ein konstanter Ausdruck wäre, würde dies Code wie diesen kompilieren:
Ich weiß nicht, ob das der wahre Grund ist, aber ich kann mir vorstellen, dass das Ausgeben eines Fehlers für diesen (häufigen?) Fehler als wichtiger angesehen wurde als das Umwandeln von 1,2
in einen konstanten Ausdruck.
UPDATE : Wie R. in einem Kommentar sagt, ist der Code ab der Einführung von VLAs kein Compilerfehler mehr.
Tags und Links c standards constants constant-expression