Ich habe mir mal diese Seite angeschaut: http://www.devbistro.com/tech-interview-questions/Cplusplus.jspund habe diese Frage nicht verstanden:
Was ist möglicherweise falsch mit dem folgenden Code?
long value;
//some stuff
value &= 0xFFFF;
Hinweis: Geben Sie dem Kandidaten einen Hinweis auf die Basisplattform, für die er entwickelt. Wenn die Person immer noch nichts Falsches am Code findet, hat sie keine Erfahrung mit C++.
Kann jemand darauf näher eingehen?
Vielen Dank!
Mehrere Antworten hier besagen, dass wenn an int
hat eine Breite von 16 Bit, 0xFFFF
ist negativ. Das ist nicht wahr. 0xFFFF
ist nie negativ.
Ein hexadezimales Literal wird durch den ersten der folgenden Typen dargestellt, der groß genug ist, um es aufzunehmen: int
, unsigned int
, long
und unsigned long
.
Wenn int
hat dann eine Breite von 16 Bit 0xFFFF
größer als der durch an darstellbare Maximalwert ist int
. Daher, 0xFFFF
ist vom Typ unsigned int
die garantiert groß genug ist, um sie darzustellen 0xFFFF
.
Bei der Auswertung werden die üblichen arithmetischen Umrechnungen durchgeführt &
das unsigned int
wird in a umgewandelt long
. Die Konvertierung einer 16-Bit unsigned int
zu long
ist wohldefiniert, da jeder Wert durch ein 16-Bit darstellbar ist unsigned int
ist auch durch ein 32-Bit darstellbar long
.
Es ist keine Vorzeichenerweiterung erforderlich, da der ursprüngliche Typ nicht vorzeichenbehaftet ist, und das Ergebnis der Verwendung 0xFFFF
ist das gleiche wie das Ergebnis der Verwendung 0xFFFFL
.
Alternativ ggf int
ist dann breiter als 16 Bit 0xFFFF
ist vom Typ int
. Es ist eine vorzeichenbehaftete, aber positive Zahl. In diesem Fall sind beide Operanden vorzeichenbehaftet, und long
den größeren Konversionsrang hat, also die int
wird wieder befördert long
durch die üblichen arithmetischen Umrechnungen.
Wie andere gesagt haben, sollten Sie es vermeiden, bitweise Operationen an vorzeichenbehafteten Operanden durchzuführen, da das numerische Ergebnis davon abhängt, wie die Vorzeichen dargestellt werden.
Abgesehen davon ist an diesem Code nichts Besonderes falsch. Ich würde argumentieren, dass es eine Stilfrage ist value
wird nicht initialisiert, wenn es deklariert wird, aber das ist wahrscheinlich ein Kommentar auf Nit-Pick-Ebene und hängt vom Inhalt der ab //some stuff
Abschnitt, der ausgelassen wurde.
Es ist wahrscheinlich auch vorzuziehen, einen Integer-Typ mit fester Breite zu verwenden (wie z uint32_t
) Anstatt von long
für eine größere Portabilität, aber auch das hängt von dem Code ab, den Sie schreiben, und von Ihren Grundannahmen.
Ich denke, je nach Größe eines Long könnte das 0xffff-Literal (-1) auf eine größere Größe befördert werden, und da es sich um einen vorzeichenbehafteten Wert handelt, wird es vorzeichenerweitert und möglicherweise zu 0xffffffff (immer noch -1).
Ich nehme an, es liegt daran, dass es für long keine vordefinierte Größe gibt, außer dass es mindestens so groß sein muss wie die vorhergehende Größe (int). Abhängig von der Größe können Sie den Wert also entweder auf eine Teilmenge von Bits abschneiden (wenn long mehr als 32 Bits beträgt) oder überlaufen (wenn er weniger als 32 Bits beträgt).
Ja, Longs (gemäß der Spezifikation und danke für die Erinnerung in den Kommentaren) müssen mindestens -2147483647 bis 2147483647 (LONG_MIN und LONG_MAX) halten können.
Da ein Wert nicht initialisiert wird, bevor das ausgeführt wird, denke ich, dass das Verhalten undefiniert ist, der Wert könnte alles sein.
Die Größe des langen Typs ist plattform-/compilerspezifisch.
Was man hier sagen kann ist:
- Es ist unterzeichnet.
- Wir können das Ergebnis von value &= 0xFFFF nicht kennen; da es zum Beispiel Wert &= 0x0000FFFF sein könnte; und wird nicht das tun, was erwartet wird.
Man könnte zwar argumentieren, dass es sich um einen Pufferüberlauf oder einen anderen Fehler handelt, der wahrscheinlich ausgenutzt werden kann Stil Ding und kein Fehler, bin ich zu 99% zuversichtlich, dass die Antwort, nach der der Fragesteller sucht, diese ist value
operiert wird, bevor es zugewiesen wird. Der Wert wird willkürlicher Müll sein, und es ist unwahrscheinlich, dass das gemeint war, also ist er “potenziell falsch”.
Bei Verwendung von MSVC denke ich, dass die Anweisung das ausführen würde, was höchstwahrscheinlich beabsichtigt war – das heißt: alle bis auf die niedrigstwertigen 16 Bits des Werts löschen, aber ich bin auf andere Plattformen gestoßen, die das Literal 0xffff als äquivalent zu (short) -1 interpretieren würden. then sign extend zur Umwandlung in long, in diesem Fall hätte die Anweisung “value &= 0xFFFF” keine Wirkung. “value &= 0x0FFFF” ist expliziter und robuster.
Es gibt möglicherweise eine Menge Dinge, die mit diesem Code nicht stimmen. Auf der anderen Seite könnte es gut sein. Ohne Kontext ist es unmöglich, eine vernünftige Antwort auf diese Frage zu geben.
– James McNellis
23. November 2010 um 1:39 Uhr
@James: Vielleicht bei einigen Implementierungen, vielleicht auch nicht. Das ist aber auf jeden Fall eine schreckliche Ausrede.
– GManNickG
23. November 2010 um 1:47 Uhr
Ich habe meine Antwort zur Zeichenerweiterung gelöscht, weil sie falsch ist. Ich vermute, es ist das, wonach der Interviewer sucht, aber wenn der Interviewer danach sucht, liegen sie auch falsch.
– Allmächtig
23. November 2010 um 2:48 Uhr
Man kann “erfahren in C++” sein und nie die bitweisen Operatoren verwendet haben. C++ ist eine so große Sprache, die so viele Programmierparadigmen unterstützt, dass ich nicht sicher bin, ob es möglich ist, anhand einer Frage definitiv festzustellen, ob man Erfahrung hat.
– JohnMcG
23. November 2010 um 3:52 Uhr
Axn:
0xffff
Wille nicht befördert werden0xffffffff
auf jeden Fall –0xffff
ist immer gleich65535
was bedeutet, dass die Konstante einen Typ hatunsigned int
wennint
ist nur 16 Bit. Es wird bleiben0xffff
/65535
bei Beförderung zu along
.– Café
23. November 2010 um 5:25 Uhr