Konvertierungseinschränkungen in C ++ 11: Was ist der "Istwert nach der Konvertierung"?

8

Ist der folgende Code in C ++ 11 zulässig?

%Vor%

Der Code stammt aus der "C ++ Programmiersprache" 4. Ausgabe (Seite 150).

Wie wir wissen, ist die Eingrenzung der Konvertierung für die Listeninitialisierung nicht zulässig, und unter der Standarddefinition der Konvertierungseinschränkung haben wir:

  

Eine einschränkende Umwandlung ist eine implizite Umwandlung
  - [...]
  - Von einem Aufzählungstyp vom Typ Integer oder nicht aufgeschnitten zu einem Integer-Typ, der nicht alle Werte des ursprünglichen Typs darstellen kann, außer wenn die Quelle ein konstanter Ausdruck ist und der tatsächliche Wert nach der Konvertierung in den Zieltyp passt und den ursprünglichen Wert erzeugt wenn zurück zum ursprünglichen Typ konvertiert wird.

Überprüfen Sie die Regel der Verringerung der Konvertierung gegen den Beispielcode, ich begründe, dass der Beispielcode illegal ist, weil 0xaabb und 0xaaaabbbbccccdddd nicht in int16_t bzw. int64_t dargestellt werden können. Ist das richtig?

Aber ich verstehe den Wortlaut nicht genau "außer, wo die Quelle ein konstanter Ausdruck ist und der tatsächliche Wert nach der Umwandlung in den Zieltyp passt und den ursprünglichen Wert erzeugt, wenn zurück konvertiert wird der ursprüngliche Typ ". Ich frage mich, in welchem ​​Szenario der tatsächliche Wert nach der Konvertierung nicht in den Zieltyp passen kann. Da Konvertierungen zwischen Integer-Typen immer gültig sind (obwohl die Implementierung für den Fall definiert ist, dass der Zieltyp signiert ist und der Quellwert nicht im Zieltyp dargestellt werden kann, aber trotzdem nicht undefiniert ist), gilt immer "der Wert nach der -Konvertierung passt in den Zieltyp "? Und von diesem Standpunkt aus beginne ich mein Urteil darüber in Frage zu stellen, dass der Beispielcode die Conversion einschränkt. Wenn das der Fall ist, warum gibt der Standard etwas immer in einer Bedingung wahr? Warum sage ich nicht einfach "außer, wo die Quelle ein konstanter Ausdruck ist und der tatsächliche Wert nach der Konvertierung den ursprünglichen Wert erzeugt, wenn er wieder in den ursprünglichen Typ konvertiert wird"?

Kann mir jemand helfen, das zu klären? Danke!

    
goodbyeera 13.02.2014, 11:52
quelle

2 Antworten

5

Dies ist ein Fehler im Standard, siehe CWG-Problem 1449 . Der Text wurde in

geändert
  

von einem Integer-Typ oder nicht gekürzten Aufzählungstyp zu einem Integer-Typ, der nicht alle Werte des ursprünglichen Typs darstellen kann, außer wenn die Quelle ein konstanter Ausdruck ist, dessen Wert nach Integral-Promotions in den Zieltyp

passt

Hinweis: Der Status des Problems, DRWP, bedeutet, dass der Standard offiziell noch nicht geändert wurde, und es kann argumentiert werden, dass zumindest Ihr int64_t -Beispiel in C ++ 11 legal ist. Compiler implementieren die neuen Regeln jedoch bereits, da dies bereits die beabsichtigte Bedeutung der ursprünglichen Formulierung war.

    
hvd 13.02.2014, 12:27
quelle
0

Schauen wir uns an, wie der Wert in eine vorzeichenbehaftete Ganzzahl konvertiert wird:

  

4.7 / 3 Wenn der Zieltyp signiert ist, ist der Wert unverändert, wenn er im Zieltyp (und der Bitfeldbreite) dargestellt werden kann. Andernfalls ist der Wert implementierungsdefiniert .

Diese Konvertierungen geben also implementierungsdefinierte Werte. Eine sinnvolle Implementierung wird die Umwandlung definieren, um den entsprechenden negativen Wert für dieses Bitmuster zu erhalten, der in den Zieltyp passt.

Die Frage ist also, ob die Konvertierung zurück zum Typ des Literals den Wert erhält? Dies hängt von der implementierungsdefinierten Größe der Literaltypen ab. Die erste wird den Wert beibehalten, wenn int genau 16 Bits hat, aber nicht, wenn es größer ist (in diesem Fall wird 0xaabb signiert, und die Umwandlung ergibt einen negativen Wert). Gleichermaßen behält die Sekunde den Wert bei, wenn entweder int genau 64 Bits hat oder int kleiner ist und long long genau 64 Bits hat.

Fazit: Es kommt darauf an. Auf einer typischen aktuellen Plattform mit 32-Bit int und 64-bit long long wird die erste schmaler und die zweite nicht. Der GCC stimmt zu und gibt eine Warnung mit -pedantic aus.

    
Mike Seymour 13.02.2014 12:29
quelle

Tags und Links