2016-07-26 12 views
0

Ich bin interested Wetter Standard sagt alles über mögliche Werte von bool Typ nach dem Gießen es zu integer Typ.C++ Casting Bool zu Int - Standard

Zum Beispiel folgenden Code:

#include <iostream> 
using namespace std; 

int main() { 
    bool someValue=false; 
    *((int*)(&someValue)) = 50; 

    cout << someValue << endl; 

    return 0; 
} 

Druck 1, obwohl es zu speichern Wert gezwungen ist 50. Hat angeben Standard etwas darüber? Oder ist Compiler eine Methode für den Typ bool erzeugt wird, wie:

operator int(){ 
    return myValue !=0 ? 1 : 0; 
} 

Auch warum wie wirft folgende:

reinterpret_cast<int>(someValue) = 50; 

verboten, mit Fehler

error: invalid cast from type 'bool' to type 'int'

(Für alle oben I Benutzer GCC 5.1 Compiler.)

+7

AFAIK Ihr Code zeigt UB, wie es gegen strenge Aliasing-Regel geht. – Arunmu

+0

Auch beim Schreiben in 'someValue' kreuzt man die Speicheranforderungen für' bool' – Arunmu

+0

Warum würdest du diese Dinge überhaupt versuchen *? –

Antwort

3

Die Art, wie Sie es verwenden, zeigt UB, weil Sie außerhalb des Bool v schreiben die Grenzen von ARIY UND Sie brechen die strenge Aliasing-Regel.

Wenn Sie jedoch einen Bool haben und wollen es als ein int verwenden (dies geschieht in der Regel, wenn Sie Index in ein auf einer Bedingung basiert Array wollen), die Standard schreibt vor, dass ein true bool konvertiert in 1 und false Bool konvertiert in 0, egal was (UB offensichtlich ausgeschlossen).

Zum Beispiel wird dies garantiert ausgegeben 52 solange should_add == true.

int main(){ 
    int arr[] = {0, 10}; 
    bool should_add = 123; 
    int result = 42 + arr[should_add]; 
    std::cout << result << '\n'; 
} 
2

Diese Linie *((int*)(&someValue)) = 50; ist mindestens nicht Standard. Die Implementierung könnte einen niedrigeren Rang für bool (etwa 1 oder 2 Bytes) für int (etwa 4 Bytes) verwenden. In diesem Fall würden Sie über die Variable schreiben und möglicherweise eine andere Variable löschen.

Und wie Sie im Kommentar gesagt wurden, dank der strengen Aliasing-Regel fast jeder Zugriff durch einen Casted Pointer kann als Undefined Behavior von einem Compiler gesehen werden. Die einzige fast Recht ein (für die strenge Aliasing-Regel) wäre:

*((char *) &someValue) = 50; 

auf einem Little-Endian-System und

*(((char *) &someValue) + sizeof(bool) - 1) = 50; 

auf einem Big-Endian eines (Byte-Zugriff noch nicht sein verboten).

Wie auch immer, da die Darstellung von Bool nicht durch den Standard spezifiziert ist, kann das Schreiben von etwas in einem Bool je nach Implementierung zu True oder False führen. Zum Beispiel könnte eine Implementierung nur das niedrigste Bit berücksichtigen (wahr, wenn val & 1 ist 1, sonst 0), ein anderes könnte alle Bits berücksichtigen (wahr für irgendeinen Wert ungleich 0, falsch für nur 0). Das einzige, was der Standard sagt, ist, dass eine Umwandlung von 0 zu false führt und von einem 0 nicht zu True führt.


aber wurde durch Standard vorgeschrieben ist die Umwandlung von Bool in int:

4.5 Integral promotions [conv.prom]

...
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

So voll dies erklärt, dass ein Bool Anzeige nur 0 oder 1 geben kann - auch wenn, wie die vorherige Operation aufgerufen UB, alles könnte hier passieren, einschließlich dieser Anzeige

+0

Sorry, aber die Endian-verwandten Sachen macht keinen Sinn. Beide Operationen sind auf jedem System gültig und beide beenden die Lebensdauer des booleschen Objekts. Und wenn 'sizeof (bool> 2)' ist, können Sie auch ein 'char' in die Bytes in der Mitte schreiben. – MSalters

+0

Da das Schreiben eines 'char' die Lebensdauer des' bool' beendet, kann man nicht sagen, dass es 'true' oder' false' ist. Dieser Speicher enthält jetzt ein "char", also sind seine Werte "CHAR_MIN ... CHAR_MAX". Der Versuch, dies als 'bool' zu lesen, ist wieder Undefined Behavior durch die strikte Aliasing-Regel. – MSalters

+0

Das ist andersherum, und speziell erlaubt für etwas wie 'memcpy' zu arbeiten. IOW, Sie können ein Bool auf ein Bool kopieren, indem Sie 'char [sizeof (bool)]' als Zwischenrepräsentation verwenden. – MSalters