Forum: Compiler & IDEs Vergleich zweier uint8_t


von blue (Gast)


Lesenswert?

Hi, ich möchte zwei unsinged!!! Variablen vergleichen, aber das 
funktioniert leider nicht so einfach, da bei > und < der Type in signed 
umgewandelt wird.

Meine Frage nun wie kann ich das Kostengünstig ändern?

lg Blue

von Alfred (Gast)


Lesenswert?

blue schrieb:
> da bei > und < der Type in signed
> umgewandelt wird.

Hallo blue,

bitte sag, wie kommst Du darauf?

Beste Grüße

Alfred

von blue (Gast)


Lesenswert?

hi,

ich hab folgendes ausprobiert:
1
 uint8_t x=0;
2
       uint8_t y=0xff;
3
       if(x<y){
4
          sd.putData(0xB0, 0x11);  //schreibt 0x11 in EEprom an Adresse 0xB0
5
       }

Mit AVR-Studio kann ich dann ja den EEProm ansehen bein debuggen und da 
wird nichts an die Adresse 0xB0 geschrieben.

Ich nutze den avr-g++ als compiler da ich c++-Code habe.

lg blue

von Alfred (Gast)


Lesenswert?

blue schrieb:
> und da wird nichts an die Adresse 0xB0 geschrieben.

Dann würde ich aber sp.putData in Verdacht nehmen. Versuche mal, an der 
Stelle
eine LED zu schalten oder mach Dir ein printf dort hin. Deine 
Schlussfolgerung,
dass da eine Typumwandlung stattfindet, kann ich nicht nachvollziehen.

Wenn Du in der Simulation debuggst, wäre ich ebenfalls vorsichtig, mit 
solchen
Annahmen :-)

Beste Grüße

Alfred

von if (Gast)


Lesenswert?

blue schrieb:
> Mit AVR-Studio kann ich dann ja den EEProm ansehen beim debuggen und da
> wird nichts an die Adresse 0xB0 geschrieben.

Wenn du debuggst, wird da nichts geschrieben, oder springt er gar nicht 
in die if Abfrage?

von blue (Gast)


Lesenswert?

An allem anderen kann es nicht liegen, das funktioniert. auch das 
sd.putData(0xB0, 0x11) funktioniert.

wenn es keine Typumwandlung in c++ bei solch einem Vergleich gibt, kann 
es dann am avr-g++ liegen?
Das habe ich ja anstelle des avr-gcc eingestellt im avr-Studio.

Wenn es daran liegt, wie kann ich avr-studio dazu bringen meinen 
c++-code zu compilieren?

von blue (Gast)


Lesenswert?

ok, habs eben gefunden, es lag wirklich am avr-g++.

ich nutze jetzt das Makefile, das ich auch zum aufspielen auf den 
Roboter nutze.

Danke für die schnelle Hilfe.
lg blue

von Detlev T. (detlevt)


Lesenswert?

blue schrieb:
> ok, habs eben gefunden, es lag wirklich am avr-g++.

Das ist ja sehr schön, dass dein Problem jetzt gelöst ist. Aber warum 
teilst du jetzt nicht dein Wissen mit der Community, deren Hilfe du 
zuvor haben wolltest? Es kann ja durchaus sein, dass irgendwann 
irgendjemand ein ähnliches Problem hat.

von Andreas F. (aferber)


Lesenswert?

blue schrieb:
> unsinged!!! Variablen

Ich hab' noch nie angesengte Variablen gesehen, von daher trifft das 
doch auf alle zu.

SCNR ;-)

Andreas

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

blue schrieb:
> ok, habs eben gefunden, es lag wirklich am avr-g++.

Das glaube ich Dir nicht.

von blue (Gast)


Lesenswert?

Also, um mein neugefundenes Wissen allen zu Teil kommen zulassen. ;-)

Das Problem: Vergleich von zwei uint8_t hat nicht funktioniert.z.B. 
0xFF>0x00 hat false ergeben.

Ursache: Das Problem lag an meiner Nutzung von AVR-Studio und avr-g++. 
Da ich einfach die Adresse für avr-gcc duch die von avr-g++ ersetzt 
habe. Die main blieb aber eine main.c.

Lösung:1.: avr-gcc lassen wie es ist. Die .c im Source-Ordner löschen 
und durch einen .cc ersetzen. oder

Lösung:2.: Ebenfalls die .c durch eine .cc ersetzen und ein eindeses 
externes Makefile nutzen.(Nutze ich, da ich ein Makefile habe, das ich 
zum Download auf meinen Robter auch nutze und somit alle Einstellungen 
nicht immer neu machen muss)

@Frank M.: Sie haben sicher Recht, ich glaube es lag an meiner 
Verwendung des g++ und nicht am g++ selbst, weiß es aber nicht genau. 
Danke für die kritische Betrachtung.

Grüße blue

von Rolf Magnus (Gast)


Lesenswert?

blue schrieb:

> Ursache: Das Problem lag an meiner Nutzung von AVR-Studio und avr-g++.
> Da ich einfach die Adresse für avr-gcc duch die von avr-g++ ersetzt
> habe. Die main blieb aber eine main.c.

Was ist "die Adresse für avr-gcc"?

> Lösung:1.: avr-gcc lassen wie es ist. Die .c im Source-Ordner löschen
> und durch einen .cc ersetzen. oder
>
> Lösung:2.: Ebenfalls die .c durch eine .cc ersetzen und ein eindeses
> externes Makefile nutzen.(Nutze ich, da ich ein Makefile habe, das ich
> zum Download auf meinen Robter auch nutze und somit alle Einstellungen
> nicht immer neu machen muss)

Das verstehe ich ehrlich gesagt alles nicht. Auch bleibt unklar, was das 
mit einem falschen Vergleichsergebnis zweier uint8_t zu tun haben soll.

von Detlev T. (detlevt)


Lesenswert?

Offenbar wurde im Makefile einfach "avr-gcc" durch "avr-g++" als Text 
ersetzt.

Dass schon dadurch die Funktion des Codes verändert werden soll, halte 
ich auch für unglaubwürdig. Abgesehen von wenigen Ausnahmen (z.B. neuen 
Schlüsselworten) ist ein korrekter C-Code auch ein korrekter C++-Code.

Meine Kristallkugel sagt: Das Codebeispiel ist wahrscheinlich falsch. 
blue hat in seinem Quelltext möglicherweise "char" statt "uint8_t" 
verwendet, vielleicht kennt er gar nicht den Unterschied. Wenn dann die 
eine Compiler-Einstellung ein nacktes "char" defaultmäßig als "signed", 
die andere als "unsigned" betrachtet, kommt es halt zu einem solchen 
Verhalten. Das ist dann wirklich kein Problem des Compilers, sondern des 
Programmierers.

Compiler produzieren selbst im Idealfall nur Programme, die das tun, was 
im Quelltext steht. Compiler, die stattdessen Programme erzeugen, die 
das tun, was der Programmierer "eigentlich wollte", hat noch keiner 
erfunden. ;)

von stefan hennig (Gast)


Lesenswert?

Lieber Alfred,
ich glaube ich kann sagen, wie blue darauf kommt:

Ich zitiere:

However integral promotion can take place when operands are of the same 
type. For example, when two signed chars are added together, both are 
converted to type int before addition and the result of the operation is 
of type int. This process is known as integral promotion and it occurs 
even with unary operators such as "-" or "~".

The rules of integral promotion say that:

A char, short, bit-field (all signed or unsigned) or an enum value is 
converted to an int if an int is able to represent all values of the 
original type, otherwise the value is converted to unsigned int.

In practice this means that the value of the original object is usually 
converted to an int but possibly to an unsigned int if the original data 
type is unsigned and of the same size as an int. For example in an 
implementation with an 8 bit char, a 16 bit short and a 32 bit int, all 
chars and shorts will be promoted to signed int values. However if both 
short and int are only 16 bits, an unsigned short will be promoted to an 
unsigned int.

Anmerkung:
integral promotion findet immer statt! Das hat nichts mit balancing zu 
tun, bei dem Typen aneinander angeglichen werden, sondern dient dazu, 
die Anzahl der Implementierungen für die Operatoren überschaubar zu 
halten.

Also muss ein unsigned char in ein int gewandelt werden, wenn int größer 
als 8 Bit ist. Ich denke nicht, dass es irgendeine Implementierung mit 
8-Bit ints gibt, bin mir aber im Moment nicht sicher, ob das erlaubt ist 
oder nicht.
Alfred schrieb:
>> da bei > und < der Type in signed
>
>> umgewandelt wird.
>
>
>
> Hallo blue,
>
>
>
> bitte sag, wie kommst Du darauf?
>
>
>
> Beste Grüße
>
>
>
> Alfred

von Karl H. (kbuchegg)


Lesenswert?

> Meine Kristallkugel sagt: Das Codebeispiel ist wahrscheinlich falsch.
> blue hat in seinem Quelltext möglicherweise "char" statt "uint8_t"
> verwendet, vielleicht kennt er gar nicht den Unterschied.

Das ist für mich die plausibelste Erklärung.

> Also muss ein unsigned char in ein int gewandelt werden,
> wenn int größer als 8 Bit ist.

Eigentlich in einen unsigned int, aber so kleinlich wollen wir mal nicht 
sein. Der springende Punkt: Ein int kann alle Werte eines unsigned char 
aufnehmen. Von daher passiert bei

   if( 0xFF > 0x00 )

genau das erwartete: Der int Wert 127 wird mit dem int Wert 0 verglichen 
und als solcher als größer bewertet.

Nur dann, wenn die Variablen vom Datentyp char sind UND char per Default 
ein signed char ist, erklärt sich das vom TO beobachtete Verhalten ganz 
natürlich.

Kann natürlich auch sein, dass der eigentliche Fehler

> ich hab folgendes ausprobiert:
1
  uint8_t x=0;
2
  uint8_t y=0xff;
3
4
  if(x<y){
5
    sd.putData(0xB0, 0x11);  //schreibt 0x11 in EEprom an Adresse 0xB0
6
  }

in sd.putData liegt. Um abzuklären, ob der Vergleich wie gewollt 
funktionioniert, ist die Verwendung einer komplexen Funktion wie 
sd.putData nicht unbedingt das Mittel der Wahl. Eine Testumgebung soll 
immer so einfach wie möglich sein, damit sie nicht selbst durch Fehler 
das Testergebnis verfälscht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Eigentlich in einen unsigned int

Wieso?  Nein, der Wert 0xFF wird zu 0x00FF als singned int, denn ein
signed int kann alle Werte eines uint8_t fassen.  Das ist aber immer
noch größer als 0x0000.

Irgendwo in der Ecke wird sich unser TE aber wohl schon verrannt
haben, nur hat er so viel mit trial&error programmiert, dass er
mittlerweile gar nicht mehr nachvollziehen kann, was denn da schräg
war.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Karl heinz Buchegger schrieb:
>> Eigentlich in einen unsigned int
>
> Wieso?  Nein, der Wert 0xFF wird zu 0x00FF als singned int, denn ein
> signed int kann alle Werte eines uint8_t fassen.

Ja, da hab ich jetzt geschlafen.
Ich brauch noch einen Kaffee.

von stefan hennig (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
>> Meine Kristallkugel sagt: Das Codebeispiel ist wahrscheinlich falsch.
>> blue hat in seinem Quelltext möglicherweise "char" statt "uint8_t"
>> verwendet, vielleicht kennt er gar nicht den Unterschied.
>
> Das ist für mich die plausibelste Erklärung.

ACK. Wenn man einem signed char 0xFF zuweist, bekommt man -1. Und, 
normalerweise, eine Compilerwarnung, die man, normalerweise, ignoriert, 
um sich dann in einem Forum öffentlich zu wundern.
>
>
>> Also muss ein unsigned char in ein int gewandelt werden,
>
>> wenn int größer als 8 Bit ist.
>
>
> Eigentlich in einen unsigned int, aber so kleinlich wollen wir mal nicht
>
> sein.

NACK. Solange, und da hast Du natürlich Recht, alle Werte repräsentiert 
werden können, werden signed-typen bevorzugt. Ich könnte jetzt 
versuchen, die entsprechenden Stellen in der ISO-Doc zu suchen, aber 
wichtig ist das wirklich nicht. Unsigned Int wird nur verwendet, wenn 
z.B. sizeof(unsigned char)==sizeof(int), aber das müsste schon ein sehr 
merkwürdiger Compiler sein.

> Der springende Punkt: Ein int kann alle Werte eines unsigned char
> aufnehmen. Von daher passiert bei
>
>    if( 0xFF > 0x00 )
>
> genau das erwartete: Der int Wert 127 wird mit dem int Wert 0 verglichen
> und als solcher als größer bewertet.

(ACK) statt 127 lies: 255, aber das ändert inhaltlich genau nix.

> Nur dann, wenn die Variablen vom Datentyp char sind UND char per Default
> ein signed char ist, erklärt sich das vom TO beobachtete Verhalten ganz
> natürlich.

ACK.

von Karl H. (kbuchegg)


Lesenswert?

stefan hennig schrieb:

>>    if( 0xFF > 0x00 )
>>
>> genau das erwartete: Der int Wert 127 wird mit dem int Wert 0 verglichen
>> und als solcher als größer bewertet.
>
> (ACK) statt 127 lies: 255, aber das ändert inhaltlich genau nix.

Irgendwie ist heute bei mir der Wurm drinnen.
Gut dass ihr auf mich aufpasst. :-)

von Rolf Magnus (Gast)


Lesenswert?

stefan hennig schrieb:
> Anmerkung:
> integral promotion findet immer statt! Das hat nichts mit balancing zu
> tun, bei dem Typen aneinander angeglichen werden, sondern dient dazu,
> die Anzahl der Implementierungen für die Operatoren überschaubar zu
> halten.

Ist auf den meisten Compilern auch kein Problem, da int normalerweise 
der "natürlichen Größe" der CPU entsprechen sollte und daher ein 
kleinerer Typ eh nicht schneller wäre. Das paßt nur leider nicht für 
8-Bit-Prozessoren, da int mindestens 16 Bit breit sein muß.

stefan hennig schrieb:
> Also muss ein unsigned char in ein int gewandelt werden, wenn int größer
> als 8 Bit ist.

Und unsigned char kleiner als int. Aber eigentlich muss der Compiler 
es nicht so machen. Es gibt in C die "as-if rule", nach der der Compiler 
Dinge beliebig anders machen kann, als von der Norm vorgegeben, solange 
nur das Ergebnis gleich ist (genauer gesagt das "observable behaviour").


> Ich denke nicht, dass es irgendeine Implementierung mit 8-Bit ints gibt,

Ja, nämlich avr-gcc mit der Option -mint8.

> bin mir aber im Moment nicht sicher, ob das erlaubt ist oder nicht.

Ist es nicht. Aber ein char, der 32 Bit breit ist, wäre erlaubt, sofern 
alle anderen Typen auch mindestens so groß sind.

von Bernhard R. (barnyhh)


Lesenswert?

Karl heinz Buchegger schrieb:
> stefan hennig schrieb:
>
>>>    if( 0xFF > 0x00 )
>>>
>>> genau das erwartete: Der int Wert 127 wird mit dem int Wert 0 verglichen
>>> und als solcher als größer bewertet.
>>
>> (ACK) statt 127 lies: 255, aber das ändert inhaltlich genau nix.
>
> Irgendwie ist heute bei mir der Wurm drinnen.
> Gut dass ihr auf mich aufpasst. :-)

Protest (ich habe an der Ecke schon mal lange gesucht und bin deshalb 
"gebranntes Kind")!

0xff ist nicht 255, sondern -1.

if (0xff > 0x00) ...
wird promoted zu int:
0x00 gibt 0 - wie erwartet
0xff wird als integer aufgefaßt und gibt -1.

Damit gilt: 0xff < 0x00.
Um derartige eklige Kleinigkeiten zu verhindern, schreibe ich 0x0ff, 
sobald ich einen 8-Bit-Wert bezeichne, der in dezimaler Schreibweise 255 
bedeuten soll.

Bernhard

von (prx) A. K. (prx)


Lesenswert?

Bernhard R. schrieb:

> 0xff ist nicht 255, sondern -1.

0xff ist eine Integer-Konstante mit dem Wert 255. Erst auf dem Umweg 
über (signed) char kann daraus -1 werden. Egal wie abgebrannt du bist. 
Wenn's anders ist, dann ist das kein Standard-C, sondern irgendwas 
Anderes oder ein Programmfehler.

Zwischen 0xff und 0x0ff und 0x0000000000000ff besteht exakt garkein 
Unterschied.

von stefan hennig (Gast)


Lesenswert?

Bernhard R. schrieb:
> 0xff wird als integer aufgefaßt und gibt -1.

Nur, wenn Deine Chars signed sind, aber dann ist der Fehler bei der 
Zuweisung passiert, nicht bei der Erweiterung.

Deshalb: keine Chars verwenden, ohne Signedness anzugeben und 
Compilerwarnungen ernst nehmen und wenn möglich mit der höchsten 
Warnstufe übersetzen. (Geht manchmal nicht, wenn man Bibliotheken 
verwenden muss, die einen dann zumüllen).

Oder, um die hier herrschende Verwirrung komplett zu machen:
Annahme: char ist 8 Bit breit, int ist 16 Bit breit.
1
unsigned char uca = 0xFFu;
2
unsigned int  uia = 0xFFu;
3
4
if (uca < -2 ) {
5
  // wird nie erreicht
6
}
7
8
if (uci < -2 ) {
9
  // wird immer erreicht
10
}

Grund: Im ersten Fall wird uca in den (signed) Integer 255 gewandelt. Im 
zweiten Fall wird -2 als 0xFFFEu repräsentiert und anschließend werden 
zwei unsigned Integer verglichen.

Alles streng nach ISO. Ich weiß auch nach mehr als 10 Jahren im Geschäft 
immer noch nicht, warum man ausgerechnet C für Embedded Programmierung 
nimmt...

von Gascht (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Wieso?  Nein, der Wert 0xFF wird zu 0x00FF als singned int, denn ein
> signed int kann alle Werte eines uint8_t fassen.

Wenn 0xFF aber schon signed ist, dann wird daraus 0xFFFF

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gascht schrieb:

> Wenn 0xFF aber schon signed ist, dann wird daraus 0xFFFF

Siehe ${subject}: es ging um uint8_t-Datentypen.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Bernhard R. schrieb:
>
>> 0xff ist nicht 255, sondern -1.
>
> 0xff ist eine Integer-Konstante mit dem Wert 255.

Und das wiederrum ist so, weil alle hexadezimalen Konstanten den 
Datentyp unsigned haben.

8 und 0x8 sind also 2 verschiedene Dinge:

8     ist ein signed Integer
0x8   ist ein unsigned Integer

(Übrigens: oktale Konstanten sind ebenfalls unsigned)

von Andreas F. (aferber)


Lesenswert?

Karl heinz Buchegger schrieb:
>> 0xff ist eine Integer-Konstante mit dem Wert 255.
> Und das wiederrum ist so, weil alle hexadezimalen Konstanten den
> Datentyp unsigned haben.

Selbst wenn es ein signed int wäre, wäre der Wert immer noch 255, da 
INT_MAX mindestens gleich 32767 ist, 255/0xff also immer im 
Wertebereich von int darstellbar ist, ohne zu einem Überlauf zu führen.

Andreas

von Bernhard R. (barnyhh)


Lesenswert?

Man sollte ab und an einmal ausmisten...
und wenn es das eigene Gehirn ist!
Vor langen Jahren - damals galt noch "real programmers dont ANSI" - war 
ich auf ein sehr debug-intensives Problem - incl. einiger Nachtschichten 
- gelaufen. Dieses Problem hing zusammen mit
- Nicht-ANSI-C-Compiler
- Hexadezimal-Konstanten
- Vorzeichen-Behandlung
- ...
Jedenfalls war es für mich Anlaß für folgende Aktionen und Denkfehler:
- Hex-Konstanten erhielten eine führende "Schutz-Null", um sie als 
positiven Wert zu kennzeichnen.
- Hex-Konstanten "propagieren" ihr Vorzeichen.

Bernhard

von Detlev T. (detlevt)


Lesenswert?

Hallo ihr Schlauen,

was ergibt das hier denn:
1
int32_t x = 0x8000;
2
int32_t y = 0x8000 >> 1;
Ich bin mir da gar nicht so sicher.

von Karl H. (kbuchegg)


Lesenswert?

Detlev T. schrieb:
> Hallo ihr Schlauen,
>
> was ergibt das hier denn:
>
1
int32_t x = 0x8000;
2
> int32_t y = 0x8000 >> 1;
> Ich bin mir da gar nicht so sicher.

0x8000 ist ein unsigned, d.h. das ist die Zahl 32768
x als 32 Bit Wert, kann diese Zahl aufnehmen, also 32768

y ist die Hälfte davon: also 16384

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> y ist die Hälfte davon: also 16384

Anders sieht die Sache so aus:
1
int32_t y = (int)0x8000 >> 1;

von Detlev T. (detlevt)


Lesenswert?

Stimmt, aber irgendetwas war da. Ich habe es noch einmal nachgeschlagen. 
Etwas, was nicht tut, was man naiverweise erwartet, ist das:
1
 uint32_t  x = 1 << 15;
Weil "1" vom Compiler als ein signed int betrachtet wird, ist "1 << 15" 
gleich -32768, wird dann (signed) zu 32 BIt aufgeblasen und in x steht 
am Ende 0xFFFF8000.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Karl heinz Buchegger schrieb:
>> y ist die Hälfte davon: also 16384
>
> Anders sieht die Sache so aus:
>
>
1
int32_t y = (int)0x8000 >> 1;

Aber nur auf Systemen, wo int == int16_t ;-)

Auf einem 32-Bit-System sieht da gar nichts anders aus: es bleibt die 
Hälfte von 32768.

Gruß,

Frank

von Karl H. (kbuchegg)


Lesenswert?

Frank M. schrieb:

> Aber nur auf Systemen, wo int == int16_t ;-)

Ist C nicht herrlich :-)

Die lobende Erwähnung in "Real Programmers don't use PASCL" hat es sich 
wirklich redlich verdient.

von Detlev T. (detlevt)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ist C nicht herrlich :-)

Yupp!

Frage: Wenn C schrecklich ist, muss dann C++ nicht noch schrecklicher 
sein? ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Detlev T. schrieb:

> Frage: Wenn C schrecklich ist, muss dann C++ nicht noch schrecklicher
> sein? ;)

Außerdem müsste B besser und D noch schlimmer sein. :-)

von Rolf Magnus (Gast)


Lesenswert?

stefan hennig schrieb:

> Deshalb: keine Chars verwenden, ohne Signedness anzugeben

Außer denen, wo Text drin gespeichert werden soll.

Detlev T. schrieb:
> Frage: Wenn C schrecklich ist, muss dann C++ nicht noch schrecklicher
> sein? ;)

Und C# ist so schrecklich, daß man es hinter Gitter stecken wollte. 
Leider ist es aber irgendwie vor dem Gitter gelandet. ;-)

von Detlev T. (detlevt)


Lesenswert?

Jörg Wunsch schrieb:
> Außerdem müsste B besser und D noch schlimmer sein. :-)

Ogottogott. Was ist dann erst mit P-Code? :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Detlev T. schrieb:
> Was ist dann erst mit P-Code? :-)

Das ist doch Pseudo-Code, der spielt in einer anderen Liga. :-)

von Detlev T. (detlevt)


Lesenswert?

Jörg Wunsch schrieb:
> Das ist doch Pseudo-Code

Du meinst, der sieht nur so aus als wäre er schrecklich? :-)

von (prx) A. K. (prx)


Lesenswert?

Karl heinz Buchegger schrieb:

> 8     ist ein signed Integer
> 0x8   ist ein unsigned Integer
> (Übrigens: oktale Konstanten sind ebenfalls unsigned)

Nixda. Ist beides wertabhängig, anfangend mit signed int, nur geht es 
unterschiedlich weiter:

Dezimal: int => long int => unsigned long int
Oktal/Hex: int => unsigned int => long int => unsigned long int

0x4000 ist also signed int,
0x8000 bei 16bit unsigned int.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Karl heinz Buchegger schrieb:
>
>> 8     ist ein signed Integer
>> 0x8   ist ein unsigned Integer
>> (Übrigens: oktale Konstanten sind ebenfalls unsigned)
>
> Nixda.

Mea Culpa.
Platsch  (das war die Seifenblase die soeben zerplatz ist)

Du hast recht.
(Sowohl der Draft als auch gcc stimmen mit dir überein)

Das wär auch zu einfach gewesen, wenn es da eine einfche Regel gäbe.
0x4000 ist tatsächlich signed, 0x8000 ist tatsächlich unsigned

Hmm
Das bedeutet für mich: Lieber einen Suffix anhängen als auf irgendwelche 
Werte vertrauen.
1
6.4.4.1 Integer constants
2
3
5 The type of an integer constant is the first of the corresponding
4
  list in which its value can be represented.
5
6
                                             Octal or Hexadecimal
7
Suffix                   DecimalConstant        Constant
8
-----------------------------------------------------------------------
9
  none                     int                  int
10
                           long int             unsigned int
11
                           long long int        long int
12
                                                unsigned long int
13
                                                long long int
14
                                                unsigned long long int

Hex Konstanten geben sich das volle Programm.
Das ist bei einem Wechsel von 16-Bit int zu 32-Bit int dann speziell 
ganz besonders lustig, wenn man so Spielchen mit Bitverschieberein 
macht, die davon abhängen ob das im Original signed oder unsigned war


   ( 0x4000 << 1 ) >> 1

liefert dann auf einem 32 Bit System ein anderes Ergebnis als auf einem 
16 Bit System.

OK. Um der Wahrheit genüge zu tun: Schiebereien mit signed Werten sind 
ja sowieso undefined. Von daher ist das gedeckt (Ich darf kein Ergebnis 
erwarten und als richtig definieren). Aber lästig könnte das schon sein.


Darüber hab ich mir ehrlich gesagt noch nie wirklich Gedanken gemacht, 
aber das sollte ich mal tun, was da so an Fallstricken im Verborgenen 
lauert. Im Moment ist meine Conclusio: Häng einen Suffix an wenn du 
unsigned willst, dann gibts keine Überraschungen.


Danke für die Aufklärung.

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:

> Außerdem müsste B besser und D noch schlimmer sein. :-)

Für B ist das anzunehmen, jedenfalls aus Sicht von Ritchie, sonst hätte 
er es bei B belassen und nicht C draus gemacht.

Was D angeht bin ich etwas anderer Ansicht als dessen Erfinder. Für 
einen Nachfolger von C m.E. deutlich zu kurz gesprungen.

von (prx) A. K. (prx)


Lesenswert?

Bernhard R. schrieb:

> - gelaufen. Dieses Problem hing zusammen mit
> - Nicht-ANSI-C-Compiler
> - Hexadezimal-Konstanten
> - Vorzeichen-Behandlung

Yep, vor ANSI war dieses Thema ein bischen offen. Es gab 2 Fraktionen. 
Die Einen bestanden schon damals auf auf value preservation, wie ANSI es 
später definierte, die Anderen favorisierten sign preservation, bei der 
im Zweifelsfall stets "unsigned" gewinnt. Es war schon damals klüger, 
sich nicht von solchen Feinheiten abhängig zu machen. Ich hatte mir 
daher den Spass erlaubt, beides zu implementieren, d.h. wählbar.

von (prx) A. K. (prx)


Lesenswert?

Karl heinz Buchegger schrieb:

> Das ist bei einem Wechsel von 16-Bit int zu 32-Bit int dann speziell
> ganz besonders lustig,

Wie wär's damit:
1
void f(void)
2
{
3
        if (-0x8000 <= 0)
4
                printf("Hip!\n");
5
        if (-32768 <= 0)
6
                printf("Hop!\n");
7
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.