2013-08-06 5 views
5

Ich bin in Bezug auf die folgende Codezeile durch ein E-Mail-Argument zu lesen:Gibt ANSI C tatsächlich an, welche Bytes beim Typisieren auf eine kleinere Ganzzahl verwendet werden?

p = (unsigned char)random(); 

Die Zufallsfunktion eines lange zurückkehrt, und jemand sagt, dass dies nicht sicher ist, weil es möglich ist, dass die Typumwandlung den MSB könnte nehmen statt das LSB. Ich weiß, dass die Typumwandlung auf x86 LSB zurückgeben würde, aber ich kann keine Information darüber finden, ob dies tatsächlich von ANSI C vorgeschrieben ist oder ob es eines dieser implementierungsspezifischen "undefinierten Verhaltensweisen" ist.

+1

Die Frage ist interessant und die Antwort wissenswert, aber im echten Code sollte man danach streben, Verwirrung zu beseitigen. Mit anderen Worten, wenn Sie den Code zu diesem ändern, gibt es keine Frage darüber, welches Byte verwendet wird: 'p = (unsigned char) (random()% 256)'. Dies wird verhindern, dass sich zukünftige Leser Ihres Codes dasselbe fragen. In der Regel sollten Sie keinen Code schreiben, der auf detaillierten Kenntnissen der zu verarbeitenden Standards beruht. –

+0

In der Tat ist die Besetzung nicht notwendig; Sie können jedem beliebigen numerischen Typ einen beliebigen numerischen Typ zuweisen, und dieser wird implizit wie von einer Umwandlung konvertiert. –

+0

@KeithThompson: Compiler können warnen, wenn eine potenziell verlustbehaftete Konvertierung ohne Umwandlung verwendet wird, obwohl ... – Christoph

Antwort

6

Dies ist in der C-Norm spezifiziert.

C99 in 6.3.1.3p2 sagt:

„Andernfalls, wenn der neue Typ unsigned ist, wird der Wert durch wiederholtes Addieren oder Subtrahieren einer mehr als der Maximalwert umgewandelt wird, die in den neuen dargestellt werden kann Geben Sie ein, bis der Wert im Bereich des neuen Typs liegt. "

Auf einem Zweierkomplement-System bedeutet es, die niedrigstwertigen Bits zu nehmen.

+0

Bei der Konvertierung in einen * signierten * -Typ kann der Zieltyp jedoch nicht den Wert darstellen, das Ergebnis ist implementierungsdefiniert (oder es kann ein implementationsdefiniertes Signal auslösen, aber ich kenne keinen Compiler, der das tut. –

+0

@KeithThompson: Wie genau muss die Dokumentation einer Implementierung das Verhalten beschreiben? Könnte eine Implementierung legitim spezifizieren, dass ein Wert N direkt außerhalb des Bereichs -32768..32767 einem 16-Bit-Typ mit Vorzeichen zugewiesen wird, der etwas wie N + 65536 * __ INDETERMINATE_VALUE, aber eine explizite Typumwandlung in ein vorzeichenbehaftetes 16-Bit speichert Typ wird die kanonische Darstellung speichern? – supercat

+0

@supercat: In beiden Fällen gibt es eine Konvertierung; Ein Cast (nicht "typecast") spezifiziert nur die gleiche Konvertierung, die implizit ohne Cast durchgeführt worden wäre. Ich nehme etwas wie "int n = too_big;" gegenüber "int n = (int) too_big;'. Bei einer * normalen * Implementierung ergeben beide Konvertierungen das gleiche Ergebnis, und ich vermute, dass das Standard-Komitee davon ausgegangen ist, dass dies der Fall ist. Aber ich denke, dass die Formulierung etwas Spielraum lässt: "Entweder ist das Ergebnis implementierungsdefiniert oder es wird ein implementierungsdefiniertes Signal erzeugt." (N1570 6.3.1.3p3) –

Verwandte Themen