Discussion:
Compilerfehler -> comparing signed and unsigned
(zu alt für eine Antwort)
Sascha Fuhrmann
2004-09-06 10:52:48 UTC
Permalink
Hallo zusammen,

bin gerade dabei, mich etwas mit C++ zu beschäftigen, und führe dazu die
Übungen aus meinem Buch durch.

Bei folgendem Code schmeisst mir dder Compiler immer die Warnung aus,
dass in Zeile 21 (die While-Schleife) 'signed' und 'unsigned' Werte
verglichen würden, was aber meiner Meinung nach nicht zutrifft.

-----schnipp-----
#include <iostream>
using namespace std;

int main()
{
typedef unsigned short ushort;
typedef unsigned long ulong;

ushort iSmall;
ulong iLarge;

const ushort iMAXSMALL = 65535;

cout << "Bitte eine kleine Zahl eingeben: ";
cin >> iSmall;
cout << "Bitte eine grosse Zahl eingeben: ";
cin >> iLarge;

cout << "Klein: " << iSmall << "...";

while(iSmall < iLarge && iLarge > 0 && iSmall < iMAXSMALL)
{
if (iSmall % 5000 == 0)
{
cout << ".";
}
iSmall++;
iLarge-=2;
}
cout << "\nKlein: " << iSmall << " Gross: " << iLarge << endl;

return 0;
}
-----schnapp-----

Wenn ich die Bedingung "iSmall < iLarge" rausnehme, dann erscheint die
Meldung nicht :(
Ich bin mir aber ziemlich sicher, dass ich die Variablen in den Zeilen 9
und 10 durch die Zeilen 6 und 7 (typedef) ganz klar als "unsigned"
deklariere.
Oder will mir der Compiler einfach nur sagen, dass ich "short int" und
"long int" vergleiche?!?

Wisst Ihr, was der Compiler dort genau anmeckert?

Vielen Dank für Eure Hilfe.
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Steffen Rauh
2004-09-06 12:48:48 UTC
Permalink
Post by Sascha Fuhrmann
Bei folgendem Code schmeisst mir dder Compiler immer die Warnung aus,
dass in Zeile 21 (die While-Schleife) 'signed' und 'unsigned' Werte
verglichen würden, was aber meiner Meinung nach nicht zutrifft.
while(iSmall < iLarge && iLarge > 0 && iSmall < iMAXSMALL)
Wisst Ihr, was der Compiler dort genau anmeckert?
Er meckert darüber, dass er vorzeichenbehaftete Werte mit vorzeichenlosen
Werten vergleicht. Deine Variablen sind zwar vorzeichenlos, aber "0" wird
der Compiler als normalen vorzeichenbehafteten Integer interpretieren,
solange du ihm nicht explizit etwas anderes sagst (z.B. über einen Cast).

MfG,
Steffen Rauh
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Sascha Fuhrmann
2004-09-06 13:34:59 UTC
Permalink
Post by Steffen Rauh
Deine Variablen sind zwar vorzeichenlos, aber "0" wird
der Compiler als normalen vorzeichenbehafteten Integer interpretieren,
Wenn Du das sagst, glaube ich es einfach mal, auch wenn mir schleierhaft
ist, warum er den Fehler nicht mehr bringt, wenn ich die Bedingung
"iSmall < iLarge" rausnehme, "iLarge > 0" aber immer noch vorhanden
ist?! Kannst Du mir das erklären?
Post by Steffen Rauh
solange du ihm nicht explizit etwas anderes sagst (z.B. über einen Cast).
Soweit bin ich noch nicht, werde es aber in Erinnerung behalten ;)

Vielen Dank für Deine Antworten.
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Steffen Rauh
2004-09-06 14:44:29 UTC
Permalink
Post by Sascha Fuhrmann
Post by Steffen Rauh
Deine Variablen sind zwar vorzeichenlos, aber "0" wird
der Compiler als normalen vorzeichenbehafteten Integer interpretieren,
Wenn Du das sagst, glaube ich es einfach mal, auch wenn mir schleierhaft
ist, warum er den Fehler nicht mehr bringt, wenn ich die Bedingung
"iSmall < iLarge" rausnehme, "iLarge > 0" aber immer noch vorhanden
ist?! Kannst Du mir das erklären?
Denkbar wäre noch, dass der Compiler für den Vergleich der beiden Variablen
den ushort zu einem int erweitert. Da ushort komplett in einem int
aufgenommen werden kann, besteht für den Compiler keine Veranlassung eine
Konvertierung in einen vorzeichenlosen Datentyp durchzuführen. Durch einen
Cast dürfte das auch wieder zu korrigieren sein.

Grundsätzlich ist es aber immer problematisch, Datentypen unterschiedlicher
Größe oder unterschiedlicher Vorzeichenbehaftung miteinander zu vergleichen.
Das kann schnell ins Auge gehen, wenn man sich nicht absolut sicher ist, was
man da eigentlich macht.

MfG,
Steffen Rauh
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Sascha Fuhrmann
2004-09-06 22:17:21 UTC
Permalink
Post by Steffen Rauh
Grundsätzlich ist es aber immer problematisch, Datentypen unterschiedlicher
Größe oder unterschiedlicher Vorzeichenbehaftung miteinander zu vergleichen.
Ok, werde mich in der Praxis dran halten, wenn ich irgendwann mal soweit
bin. Vielen Dank!
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Sascha Fuhrmann
2004-09-06 12:36:44 UTC
Permalink
Ich vergaß, zu erwähnen, dass ich die aktuelle Version des Borland C++
Compilers einsetze.
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Dirk Clemens
2004-09-06 15:00:32 UTC
Permalink
Post by Sascha Fuhrmann
Hallo zusammen,
ushort iSmall;
ulong iLarge;
while(iSmall < iLarge && iLarge > 0 && iSmall < iMAXSMALL)
Der Fehler liegt im Teil 'iSmall < iLarge'.
ushort wird bei Rechenoperationen implizit zu int gewandelt
und dann mit einem ulong verglichen.
Daher der signed/usigned Fehler.

Lemmi
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Markus Schaaf
2004-09-06 18:41:17 UTC
Permalink
Post by Dirk Clemens
Post by Sascha Fuhrmann
Hallo zusammen,
ushort iSmall;
ulong iLarge;
while(iSmall < iLarge && iLarge > 0 && iSmall < iMAXSMALL)
Der Fehler liegt im Teil 'iSmall < iLarge'.
ushort wird bei Rechenoperationen implizit zu int gewandelt
und dann mit einem ulong verglichen.
Warum sollte der Compiler das machen? Und wie vergleicht er
einen »int« mit einem »unsigned long«?
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Falk Tannhäuser
2004-09-06 19:27:33 UTC
Permalink
Post by Markus Schaaf
Post by Dirk Clemens
Der Fehler liegt im Teil 'iSmall < iLarge'.
ushort wird bei Rechenoperationen implizit zu int gewandelt
und dann mit einem ulong verglichen.
Warum sollte der Compiler das machen?
Wegen §§ 5/9 und 4.5/1?
"[...] the integral promotions (4.5) shall be performed on both operands.
Then, if either operand is unsigned long the other shall be converted
to unsigned long. [...]"
Also wird erst der 'ushort' zu 'int' (oder 'unsigned int', falls 'int'
nicht alle Werte von 'ushort' darstellen kann, was auf Maschinen der
Fall wäre, wo sizeof(unsigned short) == sizeof(int) ist) promoviert und
dann weiter zu 'unsigned long'.
Allerdings bleibt der Wert dabei erhalten, so dass es keine Probleme
geben kann, wie sie beim Vergleich negativer Ganzzahlwerte mit
vorzeichenlosen Ganzzahlwerten auftreten (s.u.) und die Warnung
m.E. witzlos ist.

Und wie vergleicht er
Post by Markus Schaaf
einen »int« mit einem »unsigned long«?
Nach §§ 5.9/2 und 5/9 wird der 'int'-Wert in 'unsigned long'
konvertiert, wobei nach § 4.7/2 die Modulo-2^n-Arithmetik
angewendet wird. Dies hat z.B. zur Folge, dass (-1 < 1UL)
lustigerweise 'false' ergibt...

MfG
Falk
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Markus Schaaf
2004-09-07 07:39:09 UTC
Permalink
Post by Falk Tannhäuser
Post by Markus Schaaf
Warum sollte der Compiler das machen?
Wegen §§ 5/9 und 4.5/1?
Darauf wollte ich hinaus. Am Ende der Promotion-Kette haben aber
beide Operanden wieder den gleichen Typ (hier »unsigned long«),
nicht einer »int« und der andere was anderes. Was soll das also
für eine Begründung dieser Vorzeichen-Warnung sein? Außerdem muß
solch eine Warnung natürlich vor jeder Promotion generiert werden.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Sascha Fuhrmann
2004-09-06 22:15:52 UTC
Permalink
Post by Dirk Clemens
Der Fehler liegt im Teil 'iSmall < iLarge'.
ushort wird bei Rechenoperationen implizit zu int gewandelt
und dann mit einem ulong verglichen.
Das scheint mir eine plausible Erklärung zu sein; hätten der Autor ja
auch mal drauf hinweisen können ;) Vielen Dank!!!
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Bastian Blank
2004-09-06 13:43:57 UTC
Permalink
Post by Sascha Fuhrmann
Bei folgendem Code schmeisst mir dder Compiler immer die Warnung aus,
dass in Zeile 21 (die While-Schleife) 'signed' und 'unsigned' Werte
verglichen würden, was aber meiner Meinung nach nicht zutrifft.
[...]
Post by Sascha Fuhrmann
while(iSmall < iLarge && iLarge > 0 && iSmall < iMAXSMALL)
Seit wann ist in C++ eine allein stehende Zahl unsigned?

Ein "iSmall < iLarge && iLarge && iSmall < iMAXSMALL" hätte sowieso den
gleichen Effekt.

Bastian
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Sascha Fuhrmann
2004-09-06 22:12:58 UTC
Permalink
Post by Bastian Blank
Seit wann ist in C++ eine allein stehende Zahl unsigned?
Wie bereits erwähnt, muss sich die Meldung auf die Bedingung 'iSmall <
iLarge' beziehen, und nicht auf 'iLarge > 0', da die Meldung nicht
aufscheint, wenn ich ersteres weglasse!
Post by Bastian Blank
Ein "iSmall < iLarge && iLarge && iSmall < iMAXSMALL" hätte sowieso den
gleichen Effekt.
Das weiss ich mittlerweile auch, aber zu dem Zeitpunkt war ich halt noch
nicht so weit, und ich führe die Beispielübungen so durch, wie sie im
Buch beschrieben sind.

Btw: Dein Codeschnipsel bringt den gleichen Fehler, was die These
untermauert, dass es nicht an dieser Bedingung liegt.

Trotzdem danke für Dein Bemühen!
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Markus Schaaf
2004-09-07 07:44:22 UTC
Permalink
Post by Bastian Blank
Seit wann ist in C++ eine allein stehende Zahl unsigned?
Falls Du eine Zahl ohne Suffix meinst: Auf einer 16-Bit-
Architektur z.B. ist das Literal »50000« »unsigned«.
Auch jede Oktal- und Hexadezimalzahl ist »unsigned«, wenn
sie nicht größer als »UINT_MAX« ist.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Horst Kraemer
2004-09-07 05:50:31 UTC
Permalink
Post by Sascha Fuhrmann
Hallo zusammen,
bin gerade dabei, mich etwas mit C++ zu beschäftigen, und führe dazu die
Übungen aus meinem Buch durch.
Bei folgendem Code schmeisst mir dder Compiler immer die Warnung aus,
dass in Zeile 21 (die While-Schleife) 'signed' und 'unsigned' Werte
verglichen würden, was aber meiner Meinung nach nicht zutrifft.
-----schnipp-----
#include <iostream>
using namespace std;
int main()
{
typedef unsigned short ushort;
typedef unsigned long ulong;
ushort iSmall;
ulong iLarge;
const ushort iMAXSMALL = 65535;
cout << "Bitte eine kleine Zahl eingeben: ";
cin >> iSmall;
cout << "Bitte eine grosse Zahl eingeben: ";
cin >> iLarge;
cout << "Klein: " << iSmall << "...";
while(iSmall < iLarge && iLarge > 0 && iSmall < iMAXSMALL)
{
if (iSmall % 5000 == 0)
{
cout << ".";
}
iSmall++;
iLarge-=2;
}
cout << "\nKlein: " << iSmall << " Gross: " << iLarge << endl;
return 0;
}
-----schnapp-----
Wenn ich die Bedingung "iSmall < iLarge" rausnehme, dann erscheint die
Meldung nicht :(
Ich bin mir aber ziemlich sicher, dass ich die Variablen in den Zeilen 9
und 10 durch die Zeilen 6 und 7 (typedef) ganz klar als "unsigned"
deklariere.
Oder will mir der Compiler einfach nur sagen, dass ich "short int" und
"long int" vergleiche?!?
Wisst Ihr, was der Compiler dort genau anmeckert?
Die Warnung beim Vergleich von unsigned short und unsigned long ist
schlicht ein Bug. Das von dieser Art Warnung fokussierte Problem ist
folgendes: Die Konvertierungsregeln beim Vergleich verschiedener
ganzzahliger Typen koennen zu möglicherweise unerwarteten mathematisch
"falschen" Resultaten fuehren, wenn der signed-Typ einen negativen
Wert enthaelt, So ergibt

int i = -1;
unsigned u = 1;

i<u

i.a. nicht "wahr". Das Problem tritt dann auf, wenn im Zuge der
Konvertierung ein signed-Typ, der einen *negativen* Wert enthält,
implizit in einen unsigned-Typ gewandelt wird, und der negative
signed-Wert damit zerstört wird.

Bei ushort <op> ulong wird zunaechst (auf Deinem System) ushort in int
gewandelt. Diese sogenannten unaeren Konvertierungen erhalten
garantiert den Wert. Dann wird der resultierende positive int in ulong
gewandelt und die beiden ulongs werden verglichen. Damit gibt es
keinen Grund zu einer Warnung. Moeglicherweise betrachtet der Compiler
den Vergleich int <op> ulong *nach* der Zwischenkonventierung
ushort->int und erkennt hier ein mögliches Problem - was er aber nicht
sollte. Compiler sind eben auch Menschen ;-)
--
Horst
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Sascha Fuhrmann
2004-09-10 18:33:40 UTC
Permalink
Post by Horst Kraemer
Bei ushort <op> ulong wird zunaechst (auf Deinem System) ushort in int
gewandelt. Diese sogenannten unaeren Konvertierungen erhalten
garantiert den Wert. Dann wird der resultierende positive int in ulong
gewandelt und die beiden ulongs werden verglichen. Damit gibt es
keinen Grund zu einer Warnung. Moeglicherweise betrachtet der Compiler
den Vergleich int <op> ulong *nach* der Zwischenkonventierung
ushort->int und erkennt hier ein mögliches Problem - was er aber nicht
sollte.
Vielen Dank für die ausführliche Erläuterung!
--
Gruß
Sascha
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+***@bud.prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-***@bud.prima.de
Loading...