Frage

C definiert mindestens 3 Ebenen des "konstanten Ausdrucks":

  • konstanter Ausdruck (nicht qualifiziert)
  • arithmetischer konstanter Ausdruck
  • ganzzahliger konstanter Ausdruck

    6.6 Absatz 3 lautet:

    Konstante Ausdrücke dürfen keine Zuweisung, Inkrementierung, Dekrementierung, Funktionsaufruf, oder Kommaoperatoren, außer wenn sie in einem Unterausdruck enthalten sind, der nicht vorhanden ist ausgewertet.

    Bedeutet dies, dass 1,2 kein konstanter Ausdruck ist?

    Absatz 8 lautet:

    Ein arithmetischer konstanter Ausdruck muss einen arithmetischen Typ haben und darf nur haben Operanden, die ganzzahlige Konstanten, schwebende Konstanten, Aufzählungskonstanten und Zeichen sind Konstanten und Größe der Ausdrücke. Cast-Operatoren in einem arithmetischen konstanten Ausdruck konvertiert nur arithmetische Typen in arithmetische Typen, außer als Teil eines Operanden in a Größe des Operators, dessen Ergebnis eine Ganzzahlkonstante ist.

    Was sind die Operanden in (union { uint32_t i; float f; }){ 1 }.f? Wenn 1 der Operand ist, ist dies vermutlich ein arithmetischer konstanter Ausdruck, aber wenn { 1 } der Operand ist, ist dies eindeutig nicht der Fall.

    Bearbeiten: Eine weitere interessante Beobachtung: 7.17 Absatz 3 erfordert, dass das Ergebnis von offsetof ein ganzzahliger konstanter Ausdruck vom Typ size_t ist, die Standardimplementierungen von offsetof jedoch, soweit ich das beurteilen kann, nicht muss nach dem Standard ganzzahlige konstante Ausdrücke sein. Dies ist natürlich in Ordnung, da eine Implementierung (unter 6.6 Absatz 10) andere Formen konstanter Ausdrücke akzeptieren oder das offsetof-Makro als __builtin_offsetof anstatt über eine Zeigersubtraktion implementieren darf. Das Wesentliche dieser Beobachtung ist jedoch, dass Sie, wenn Sie offsetof in einem Kontext verwenden möchten, in dem ein ganzzahliger konstanter Ausdruck erforderlich ist, das von der Implementierung bereitgestellte Makro wirklich verwenden und nicht Ihr eigenes rollen müssen.

War es hilfreich?

Lösung

Basierend auf Ihrer Lesart ist 1,2 kein konstanter Ausdruck. Ich weiß nicht, warum es nicht so ist, nur dass ich Ihnen zustimme, dass es nicht so ist (trotz der Tatsache, dass es wahrscheinlich sein sollte).

6.5.2 gibt zusammengesetzte Literale als Postfix-Operator an. Also in

(union { uint32_t i; float f; }){ 1 }.f

Die Operanden sind (union { uint32_t i; float f; }){ 1 } und f für den .-Operator. Es ist kein arithmetischer konstanter Ausdruck, da das erste Argument ein union-Typ ist, sondern ein konstanter Ausdruck.

UPDATE: Ich habe dies auf eine andere Interpretation des Standards gestützt.

Meine frühere Argumentation war, dass (union { uint32_t i; float f; }){ 1 }.f die Kriterien für einen konstanten Ausdruck erfüllt und daher ein konstanter Ausdruck ist. Ich denke immer noch, dass es die Kriterien für einen konstanten Ausdruck erfüllt (6.6 Absatz 3), aber dass es sich nicht um einen der Standardtypen konstanter Ausdrücke (Ganzzahl, Arithmetik oder Adresse) handelt und daher nur durch 6.6 Absatz ein konstanter Ausdruck sein muss Dies ermöglicht implementierungsdefinierte konstante Ausdrücke.

Ich wollte auch zu Ihrer Bearbeitung kommen. Ich wollte argumentieren, dass die "Hack" -Implementierung von offsetof ein konstanter Ausdruck ist, 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 kein ganzzahliger konstanter Ausdruck. und ist daher außerhalb von 6.6 Absatz 10 ungültig.

Andere Tipps

Wenn 1,2 ein konstanter Ausdruck wäre, könnte Code wie dieser kompiliert werden:

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

Ich weiß nicht, ob dies 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 1,2 in einen konstanten Ausdruck umzuwandeln.

UPDATE : Wie R. in einem Kommentar ausführt, ist der Code about seit Einführung der VLAs kein Compilerfehler mehr.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top