C++ kann Verzweifelung verursachen

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ kann Verzweifelung verursachen

Beitrag von Mathias »

IAR Embedded Workbench

Ist dies ein Clone von Atmel-Studio ?


"int" ist ohnehin nicht "eindeutig", sondern Architektur- und damit Compiler-Abhängig.

Beim Integer würde ich mich mal bei Pascal verlassen, auch wen es jetzt bei FPC immer 32Bit ist.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: C++ kann Verzweifelung verursachen

Beitrag von Socke »

Mathias hat geschrieben:Beim Integer würde ich mich mal bei Pascal verlassen, auch wen es jetzt bei FPC immer 32Bit ist.

Integer ist kein Datentyp sonder nur ein Alias - entweder für ShortInt im Default-Modus oder für Longint im ObjFPC-/Delphi-Modus.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: C++ kann Verzweifelung verursachen

Beitrag von siro »

Der IAR hat mit Atmel nichts zu tun.

Die haben eine komplett eigene IDE und sogar eigene C-Compiler für verschiedene Prozessoren.
Unsere Firma hat sich die "teure" IDE für die Arm Prozessoren gekauft.
IAR hat sich sogar ein Tüv Zertifikat geben lassen.

Das sollte man sich auch mal kurz angucken:
http://www.elektronikpraxis.vogel.de/so ... es/426198/

Habe mich ein Jahr lang mit dem System rumgeqält, bin dann umgestiegen auf die Freeware LPCxpresso von NXP
Diese funktioiniert im Prinzip genauso gut und ist bis 256KByte Code Freeware
LPCXpressor benutzt die Open Source GNU Compiler.
Durch die Freeware kann ich nun auch meine privatern Projekte damit programmieren.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: C++ kann Verzweifelung verursachen

Beitrag von mschnell »

Elektronik Praxis hat geschrieben:char c1;
c1 = ~0x80;
if (c1 == ~0x80)
{ //wird nie erreicht}

Wieso beschweren die sich ?
"Char" ist genau wie "int" definitionsgemäß Compiler-abhängig. Bei manchen Compilern ist es signed, bei anderen unsigned. für die geplante Verwendung als druckbares Zeichen ist das in der Regel egal.

Wenn man mit 8 Bit großen Zahlen rechen will, sollte man (wie jeder C-Programmierer weis) "signed char" oder "unsigned char" verwenden, oder besser "uint8_t" oder "int8_t".

-Michael

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C++ kann Verzweifelung verursachen

Beitrag von Timm Thaler »

mschnell hat geschrieben:
Elektronik Praxis hat geschrieben:char c1;
c1 = ~0x80;
if (c1 == ~0x80)
{ //wird nie erreicht}

Wenn man mit 8 Bit großen Zahlen rechen will, sollte man (wie jeder C-Programmierer weis) "signed char" oder "unsigned char" verwenden, oder besser "uint8_t" oder "int8_t".


Hilft Dir hier nicht, das Problem ist ein Anderes. Der Char c1 wird vom Compiler auf 32bit erweitert.

~0x80 ist 0x7F in c1. Durch die Erweiterung wird das zu 0x0000007F. Verglichen wird es jetzt mit einer Konstante, ~0x00000080, die negiert wird zu 0xFFFFFF7F. Klar, dass das nicht gleich ist.

Über so Mist bin ich beim GCC für AVR auch schon gestolpert, weil der Compiler meinte meine 8bit-Variablen unbedingt auf 16bit aufblähen zu müssen. Da muss man dann erstmal rumcasten, um das gewünschte Format zu erzwingen.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: C++ kann Verzweifelung verursachen

Beitrag von mschnell »

Timm Thaler hat geschrieben:Der Char c1 wird vom Compiler auf 32bit erweitert


Ich vermute, Du meinst:

in der Operation "c1 == ~0x80" wird der Wert in C1 auf 32 erweitert.

Das ist natürlich korrekt (wenn wir Annehmen, dass es ein Compiler für ein 32 Bit System ist.

(Nur der Vollständigkeit halber, Vorzeichen spielen hier keine Rolle, aber da kann man ebenso verwirrende Beispiele konstruieren, da bei manchen Compilern "char" Vorzeichen-behaftet ist, bei anderen nicht.)

Es ist auch völlig logisch, da - wie bereits besprochen - unspezifizierte Integer Konstanten den Typ "int" haben, und "int" Compiler-abhängig definiert ist (bei 32 Bit Ziel-Architektur meist ein Vorzeichen-behafteter 32 Bit Wert.)

Bei unterschiedlichen Typen in einer Operation wird wenn nötig vorzeichenlos in Vorzeichen-behaftet und die kleinere Bit-Zahl auf die größere gewandelt.

Die erste Operation ist "~", die zweite Operation ist "==".

"c1 == ~0x80" wandelt also völlig logisch "0x80" in einen Vorzeichen-behafteten Wert mit entsprechend viele (z.B. 32) Bits und den Wert in C1 auf (z.B.) 32 Bit Integer, aber bei einem Compiler, bei dem char als unsigned definiert ist mit positivem Vorzeichen. (Das Ergebnis ist übrigens auch ein "int" !!!)

-Michael

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C++ kann Verzweifelung verursachen

Beitrag von Timm Thaler »

Ähm nein, Du übersiehst die Tilde.

Bei der Zuweisung wird erst 0x80 zu 0x7F bitweise invertiert. Das 0x7F = dez 127 landet dann korrekt in der 32bit-Variable als 0x0000007F.

Egal ob char signed oder unsigned ist, 0x7F ist immer dez 127 und positiv.

Beim Vergleich wird aber mit einer Konstante verglichen, bei der aus 0x00000080 bitweise negiert 0xFFFFFF7F, also dez -129 wurde.

Nun könnte man meinen, dieser Fall ist arg konstruiert. Bei Mikrocontrollern ist aber so eine bitweise Invertierung gar nicht ungewöhnlich, zum Beispiel wenn Du einen low-aktiven Port einliest, invertierst und dann auf einen bestimmten Zustand vergleichen willst. Wenn Dir dann der Compiler zu den 8 Portpins noch 8 weitere dazuerfindet...

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ kann Verzweifelung verursachen

Beitrag von Mathias »

Ich habe mal folgen Code bei meinem Arduino probiert, es kommt wie du sagst "false".
Die Grösse von c1 ist immmerhin 1.

Code: Alles auswählen

void loop() {
   char c1;
   c1 = ~0x80;
   if (c1 == ~0x80) {
      Serial.println("true");
   } else {
      Serial.println("false");
   }
   Serial.println(sizeof(c1));
}

Ich poste diesen Code im Arduino-Forum, mal gucken was die dazu sagen. :wink:

Komisch mache ich aber

Code: Alles auswählen

   c1 = ~80;
   if (c1 == ~80) {

dann kommt "true". :roll:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: C++ kann Verzweifelung verursachen

Beitrag von Timm Thaler »

Mathias hat geschrieben:Komisch mache ich aber

Code: Alles auswählen

   c1 = ~80;
   if (c1 == ~80) {

dann kommt "true". :roll:


Nee, nicht komisch.

0x80 ist entweder dez 128 im unsigned byte (0..255) oder dez -128 im signed byte (-128..127). Wird invertiert zu 127.

Dez 80 (0x50) wird invertiert zu dez -81 (0xAF). Bei der Erweiterung schleift der Compiler diesmal das Vorzeichen mit, da das führende Bit gesetzt ist. Es wird zu 0xFFAF erweitert und mit 0xFFAF verglichen, passt.

Der Witz im obigen Beispiel ist ja, dass aus einer Zahl mit Vorzeichenbit eine Zahl ohne Vorzeichenbit wird, aber wenn man das mit 8bit macht kommt dabei halt eine andere Zahl raus als wenn man das mit 16 oder 32bit macht.

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ kann Verzweifelung verursachen

Beitrag von Mathias »

Jetzt blicke ich langsam durch, der dumme C-Compiler macht aus einem gewöhnlichen char ein Signed.
Und in der If-Abfrage, macht er ein Unsigned.

Beo folgenden Code kommt ein true.

Code: Alles auswählen

   char c1;
   c1 = ~0x80;
   if (c1 == char(~0x80)) {   // oder if (c1 == 127) {
      Serial.println("true");
   } else {
      Serial.println("false");
   }

Aber wen man es auf der Binär-ebene anguckt, ist c1 immer %10000000, somit müsste die If-Abfrage immer erfüllt sein. :wink:

Ausser eben, wie du sagst, wird der char bei der If-Abfrage in einen 16Bit-Wert umgewandelt.
Man müsste dies mal mit einem Debugger genauer angucken, was da für Assembler-Befehle raus kommen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ kann Verzweifelung verursachen

Beitrag von Mathias »

Im Arduino-Forum habe ich eine Antwort bekommen, die Konstante 0x80 implementiert C++ als Integer.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: C++ kann Verzweifelung verursachen

Beitrag von mschnell »

Mathias hat geschrieben:Jetzt blicke ich langsam durch, der dumme C-Compiler macht aus einem gewöhnlichen char ein Signed.
Und in der If-Abfrage, macht er ein Unsigned.

Nee.
Ob "char" (ohne Zusatz) signed oder unsigned ist, ist Compiler-abhängig (und immer mindestens 8 Bit groß), dann aber durchgängig. Integer Konstanten (ohne Zusatz) sind immer "int", und "int" ist (soweit ich weiß immer) signed (und ebenfalls immer mindestens 8 Bit groß, aber in der Regel mindestens so viele Bit wie für einen Pointer notwendig sind).

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: C++ kann Verzweifelung verursachen

Beitrag von mschnell »

Mathias hat geschrieben:Im Arduino-Forum habe ich eine Antwort bekommen, die Konstante 0x80 implementiert C++ als Integer.

In C ist jede Integer Konstante ohne Zusatz-Angabe "int".

-Michael

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: C++ kann Verzweifelung verursachen

Beitrag von siro »

int ist nach meiner Erkenntnis immer mindestens 16 Bit groß
ob int signed oder unsigned ist, scheint nicht genormt zu sein.
Aber generell ist alles was nicht explizit gewandelt wird ein int, also auch die angegebenen Konstanten.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C++ kann Verzweifelung verursachen

Beitrag von Mathias »

Hier ist auch einer am üben mit C++:https://www.arduinoforum.de/arduino-Thread-32-Bit-Variable-beschreiben
Da liebe ich richtig mein Pascal. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten