Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » doch nicht unsigned?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ] [ 3 ]
000
29.04.2005, 21:17 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


Hoi @all,
hab mal folgende Frage

folgender schlechter Code verursacht bei mir ein wenig Kopfzerbrechen


C++:
#include <iostream>

int main(){

    unsigned char a,b;
    
    a=16,b=32;

    if(a-b>0)
        std::cout<<"Ja"<<std::endl;
    else
        std::cout<<"Nein"<<std::endl;

}



es kommt wider erwartens Nein heraus...

nehm ich jedoch unsigned int


C++:
#include <iostream>

int main(){

    unsigned int a,b;
    
    a=16,b=32;

    if(a-b>0)
        std::cout<<"Ja"<<std::endl;
    else
        std::cout<<"Nein"<<std::endl;

}


kommt wie erwartet bei dem überlauf ein Ja heraus?

Woran genau liegt das? wird bei dem vergleich nach int gecastet oder was genau passiert da?
Ist dieses Verhalten compilerabhängig oder schreibt der standard da was vor das der Compiler so schlau sein muss, dass das teil bei datentypen die kleiner als der grösste integrale datentyp sind den Überlauf selber erkennt?
--
...fleißig wie zwei Weißbrote

Dieser Post wurde am 30.04.2005 um 01:55 Uhr von Windalf editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.04.2005, 23:06 Uhr
0xdeadbeef
Gott
(Operator)


Laut Standard (4.5) ist das so korrekt:

Zitat von ISO-C++ 2003:

An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int.


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.04.2005, 23:40 Uhr
~CDW
Gast


ich kann zumindest sagen dass es bei mir auf msvc++ 6.0 genau dasselbe Verhalten ist.

Woran das liegt: ich weiß nicht wie genau sich msvc++ 6 AutorenEdition an standards hält,
also ohne gewähr und nur auf Windows und eine x86 CPU bezogen:

bei unsigned char wird intern trotzdem ein 32-bit register benutzt. der "vergleich" wird in
etwa so übersetzt: Wenn ergebnis kleiner oder gleich 0 springe zu NEIN.


Code:
SUB EAX,ECX
TEST EAX,EAX
JLE SHORT threadpr.00401045
00401025  |.PUSH threadpr.004018F0
0040102A  |. 68 A0C04000    PUSH threadpr.0040C0A0                   ;  ASCII "Ja"
0040102F  |. 68 68CD4000    PUSH threadpr.0040CD68
00401034  |. E8 F7000000    CALL threadpr.00401130
00401039  |. 83C4 08        ADD ESP,8
0040103C  |. 8BC8           MOV ECX,EAX                              ; |
0040103E  |. E8 CD000000    CALL threadpr.00401110                   ; \threadpr.00401110
00401043  |. EB 1E          JMP SHORT threadpr.00401063
00401045  |> 68 F0184000    PUSH threadpr.004018F0
0040104A  |. 68 A4C04000    PUSH threadpr.0040C0A4                   ;  ASCII "Nein"



hier ist wohl die "Übersetzungsschablone" für Größer/Kleiner vergleich des compilers schuld,
denn an sich ist es ja nicht falsch "wenn a-b kleiner gleich 0 dann gehe zu NEIN", Deine
Bedienung wird einfach negiert. Dummerweise werden aber auf einer x86 CPU beim Überlauf
die S,C (sign, carry) gesetzt. Carry signalisiert dabei die Überschreitung des Wertes.
Im Register steht auch 0FFFFFFF0h. TEST ist verinfacht eine "optimierte" Methode um zu
schauen ob das "ergebnis" 0 sei. Es setzt den Zeroflag auf 1 wenn das Ergebnis 0 ist.
ABER: JLE(jump less or equal) springt wenn S!=0 oder Z=1 (Zeroflag, wenn das Ergebnis
nach einer Operation 0 ist).

Und S(ign)- Flag wird bei einem SUB unabhängig davon gesetzt ob die Variable im Compiler
als signed oder unsigned deklariert wurde (weil die CPU nix davon weiß )

Hier liegt also IMHO ein Compilerfehler bzw. Bug vor. Wenn nämlich die
übersetzungsschablone genauso übersetzten würde wie es im Quellcode steht, würde hier
ein "JA" kommen da das ergebnis doch deutlich über null liegt . Denn dass
der S-Flag bei einem SUB gesetzt wurde nicht erst mit dem P4 eingeführt genauso
wie die auswirkungen von TEST...

Bei dem zweiten Code wo ein unsigned int ist ist der code fast identisch:

Code:
00401017  |. 2B45 F8        SUB EAX,DWORD PTR SS:[EBP-8]
0040101A  |. 85C0           TEST EAX,EAX
0040101C  |. 76 20          JBE SHORT threadpr.0040103E
0040101E  |. 68 F0184000    PUSH threadpr.004018F0



es kommt wieder 0fffffff0h raus, dieselben Flags werden gesetzt, nur steht diesesmal "wenn
grösser oder gleich gehe zu NEIN". Nun, das ist wieder so ein "optimization" Trick (nein, ich
hatte kein optimization flag an beim compilieren, das bietet die Autrenedition gar net )
wenn da nämlich 0 wäre, würde der TEST den Zero-flag auf 1 setzen, und JBE springt wenn
Z(ero)flag==0. Hier passts wieder mit der Bedienung.

Hoffe mal dass es etwas verständlich rüberkam.

Mich würde natürlich auch interessieren ob es "Bug or feature" ist. Was z.B gcc oder Inels Compiler dazu "sagen" würden.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.04.2005, 01:45 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)



Zitat:

Mich würde natürlich auch interessieren ob es "Bug or feature" ist. Was z.B gcc oder Inels Compiler dazu "sagen" würden


Ja die Frage bleibt irgendwie im Raum. Prinzipiell ist es ja praktisch, dass man selbst unsigned-Datentypen durch Subtraktion vergleichen kann ohne darauf achten zu müssen welcher nun den grösseren Wert hat.
Der Auszug von beefy sagt ja das das prinzipiell nicht ungewöhnlich ist aber das steht auch deutlich "can" was dann imho soviel heisst, dass einem ein andere Compiler den Code ggf. auch um die Ohren hauen könnte.
Insbesondere wenn man Templates benutzt ist dieses Verhalten ja eher lästig sollte man tatsächlich in einem komplizierteren Konstrukt einen ähnlichen Denkfehler aber dann nicht mit allen Datentypen getestet haben. Wenns dann irgendwann mal knallt wundert man sich es ging doch sonst so wunderbar.
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
30.04.2005, 13:11 Uhr
(un)wissender
Niveauwart


Tja, schon erstaunlich, was sich die ISO-Leute da leisten. Ich würde es ganz naiv ansonsten schlicht als Bug bezeichnen. Hoffentlich spezifizieren die in C++0x die Sachen mal korrekt, z. B. i = i++ + ++i oder die Auswertungreihenfolge der Parameter.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
30.04.2005, 13:31 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von (un)wissender:
Tja, schon erstaunlich, was sich die ISO-Leute da leisten. Ich würde es ganz naiv ansonsten schlicht als Bug bezeichnen. Hoffentlich spezifizieren die in C++0x die Sachen mal korrekt, z. B. i = i++ + ++i oder die Auswertungreihenfolge der Parameter.

Zur ersten teilausage: Zustimmung, die leisten sich schon so manches, was nicht sinnvoll erscheint
Zur zweiten Teilaussage:

Code:
i = i++ + ++i


Sollte nach wie vor undefiniert bleiben. Abgesehen davon, daß ich bezweifeln möchte, daß in den letzten 35 jahren, in denen es C gibt, jemand ein solches Feature ernstlich vermisst hätte (möglicherweise ein paar Anfänger), solltest Du dir über die Konsequenzen bewußt werden, die eine Definiertheit solcher Ausdrücke zur folge hätte (Stichworte: Seqzuencepoints und Optimierbarkeit)
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
30.04.2005, 17:55 Uhr
(un)wissender
Niveauwart


Mir ist klar, dass da eventuell die Entscheidungsfreiheit des Compilers beeinflusst wird und er so nicht optimal optimieren kann. Allerdings halte ich es für ganz übel, so etwas stillschweigend zu zulassen, ohne zumindest eine Warnung auszugeben. Das gilt auch für einige andere C++ bzw. C-Konstrukte. Ich finde die Spezifikation sollte aussagen, dass so etwas wie i++ + ++i nicht kompiliert, da es nie zuverlässig das tut, was man möchte.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
30.04.2005, 19:11 Uhr
ao

(Operator)



Zitat von ~CDW:
Mich würde natürlich auch interessieren ob es "Bug or feature" ist. Was z.B gcc oder Inels Compiler dazu "sagen" würden.

Ein Feature, kein Bug. Kurze Ganzzahlen (signed und unsigned char, signed und unsigned short) können, *bevor* damit gerechnet wird, in int ge-promotet werden (wie 0xdeadbeef oben sagte). D.h. die Subtraktion und der Vergleich werden mit einem Datentyp gemacht, der nicht bei 0 überläuft.
Unsigned int wird aber nicht zu int zurück-promotet, so dass es zum Überlauf kommt.

Genauso stehts in allen guten Büchern. Wer in C++ programmieren will, muss mehr aufpassen als andere, da hilft nix.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
30.04.2005, 20:56 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von (un)wissender:
Ich finde die Spezifikation sollte aussagen, dass so etwas wie i++ + ++i nicht
kompiliert, da es nie zuverlässig das tut, was man möchte.


Der Standard sagt bereits jetzt glasklar, daß es nicht definiert ist. Warum soll man denn Verhalten beschreiben, welches nicht definiert ist? - Eine solche Aussage würde ich in keinem Standard sehen wollen, sondern eher in der Beschreibung zu einer Compiler Option. Nehmen wir zB den den gcc:

C++:
int main() {
  int n= 0;

  n = n++ + ++n;
}


mit

Code:
gcc -Wall


compilert gibt entsprechende Warnungen. Das reicht, denke ich.


Bearbeitung:

@virtual, was sind das denn für codetag-schlampereien


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 01.05.2005 um 09:03 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
01.05.2005, 00:43 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)



Zitat:

Ein Feature, kein Bug. Kurze Ganzzahlen (signed und unsigned char, signed und unsigned short) können, *bevor* damit gerechnet wird, in int ge-promotet werden (wie 0xdeadbeef oben sagte). D.h. die Subtraktion und der Vergleich werden mit einem Datentyp gemacht, der nicht bei 0 überläuft.
Unsigned int wird aber nicht zu int zurück-promotet, so dass es zum Überlauf kommt.


Durch das Wörtchen "können" halte ich es persönlich für kein Feature (sondern eher für ne Schweinerei aber für sowas bin ich ja immer zu haben )...
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ] [ 3 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: