Beispiel
%Vor%Frage
Das Kompilieren des obigen Codes mit g++ -O0 -Wall -pedantic -ansi -std=c++11
ergibt keine Fehler (außer für eine unbenutzte Variable). Wenn ich jedoch -std=c++11
entferne, erhalte ich folgende Warnung:
Warnung: ISO C ++ verbietet Array variabler Länge
Nach diese SO Frage glaube ich, dass in C ++ 03, der Code ist ungültig. Kann jedoch jemand erklären, wie sich die Regel in C ++ 11 geändert hat?
(Diese Frage war ein Ergebnis von eine vorherige Frage antwortete ich.)
Eine Array-Grenze muss ein ganzzahliger konstanter Ausdruck sein, siehe 8.3.4 [dcl.array] / 1 (gleicher Wortlaut in C ++ 03 und C ++ 11):
Wenn der Konstanten-Ausdruck (5.19) vorhanden ist, soll er ein ganzzahliger konstanter Ausdruck sein und sein Wert größer als Null sein.
In C ++ 03 kann ein ganzzahliger Konstantenausdruck nicht durch ein Fließkomma-Literal initialisiert werden, es sei denn, er wird in den Ganzzahl-Typ umgewandelt, siehe den letzten Satz von 5.19 [expr.const] / 1:
Ein Integralkonstantenausdruck kann nur Literale (2.13), Enumeratoren,
const
Variablen oder statische Datenelemente von Integral- oder Enumerationstypen enthalten, die mit konstanten Ausdrücken initialisiert sind (8.5), Nicht-Typvorlage Parameter von Integral- oder Enumerationstypen undsizeof
-Ausdrücke. Fließende Literale (2.13.3) können nur auftreten, wenn sie in Integral- oder Aufzählungstypen umgewandelt werden.
Dies bedeutet, dass in C ++ 03 i
kein Integralkonstantenausdruck ist und daher nicht als Array gebunden verwendet werden kann.
GCC und Clang erlauben Arrays mit variabler Länge als Erweiterung zu C ++ 03, also kompiliert sie mit einer nicht konstanten Grenze, aber Sie erhalten eine Warnung mit -pedantic
. Wenn Sie den Initialisierer der Konstanten ändern, um ihn in einen ganzzahligen Typ umzuwandeln, wird i
zu einem gültigen Ausdruck für eine ganzzahlige Konstante:
Mit dieser Änderung hat das Array keine variable Länge mehr und es gibt auch keine Warnung mehr mit -pedantic
.
In C ++ 11 5.19 [expr.const] / 3 sagt:
Ein literaler Konstantenausdruck ist ein Prvalue-Kernkonstantenausdruck des Literaltyps, aber nicht des Zeigertyps. Ein Integralkonstantenausdruck ist ein Literalkonstantenausdruck des Integral- oder Unscoped-Aufzählungstyps.
Die vorhergehenden (ziemlich langen) Absätze beschreiben die Regeln für Kernkonstantenausdrücke, aber im Grunde genommen in C ++ 11 verhindert der Doppelinitialisierer i
nicht als Kernkonstantenausdruck, auch ohne eine Umwandlung, also ist es ein Integral konstanter Ausdruck und daher ein gültiges Array gebunden, also keine Warnung.