Simon schrieb:> folgendes kleines Testprogramm kommt, meiner Meinung nach, zu einenm> falschen Ergebnis.
Welcher Compiler, welche Version, welche Compileroptionen?
> erg hat den Wert -1.
Wie hast Du diesen auf einem AVR ausgeben lassen?
P.S.
Ich glaube das persönlich nicht, der Fehler muss woanders liegen.
P.P.S
Alle Variablen sind volatile deklariert, d.h. Du teilst dem Compiler
mit, dass sie an anderer Stelle (z.B. in einer ISR) beliebig abgeändert
werden könnten. Ist das Absicht? Meines Erachtens ist Dein Mini-Programm
nur die halbe Wahrheit.
Kannst Du das tatsächlich mit diesem Progrämmchen auf einem AVR
reproduzieren oder hast Du das eigentliche Programm so weit vereinfacht,
dass hier komplett der Kontext (und auch der Fehler) verlorengegangen
ist?
Frank M. schrieb:> Ich glaube das persönlich nicht, der Fehler muss woanders liegen.
Ist so, hab mich grad auch gewundert.
Ich habs mal auf die schnelle mit Arduino getestet (ATmega2560).
Jedoch gibt es eine Warning:
"warning: comparison between signed and unsigned integer expressions
[-Wsign-compare]"
Beim AtmelStudio mit einem Cortex-M4 funktioniert es richtig.
Simon schrieb:> Kann mir bitte jemand erklären was hier passiert?
Du verrechnest Äpfel mit Birnen und verlässt dich dabei auf implizite
Typumwandlungen.
my2ct schrieb:> Du verrechnest Äpfel mit Birnen und verlässt dich dabei auf implizite> Typumwandlungen.
Ja, sehe ich auch so, denn so funktioniert es, was natürlich auch
logisch ist:
Schaut dir einfach mal die Binärcodierung von -3 an und wie der
maschinenbefehl CMP funktioniert.
Zu erinnerung CPU-Register kennen keine Unterschied zwischen signed und
unsigned, die vergleichen stur die Bits.
Adam P. schrieb:> Jedoch gibt es eine Warning:> "warning: comparison between signed and unsigned integer expressions> [-Wsign-compare]"
Ich habs eben unter Linux getestet. Bei mir gibt es weder diese Warnung
noch den Fehler: Es wird "1" ausgegeben.
1
$ cc -O2 -Wall -Wextra a.c
2
$ ./a.out
3
1
4
$ cc -v
5
...
6
gcc version 8.3.0 (Debian 8.3.0-6)
Wenn, dann muss es etwas avr-gcc-spezifisches sein - eventuell in einer
speziellen Compilerversion.
my2ct schrieb:> Du verrechnest Äpfel mit Birnen und verlässt dich dabei auf implizite> Typumwandlungen.
Richtig, darauf hatte ich mich verlassen.
Ich dachte ein Vorzeichen auf jeder Seite sollte reichen.
Simon schrieb:> erg hat den Wert -1.
Das ist korrekt. Der Vergleich erfolgt im größeren Format und das ist
auf nem 8Bitter uint16_t.
Aus -3 wird somit 0xFFFD = 65533
Und 12 < 65533
Auf nem 32Bitter ist aber int > uint16_t, da int == int32_t.
Bestätige:
Sehe die Warnung auch auf AVR und es kommt -1 raus.
Die Warnung ist also mehr als berechtigt.
Bei RP2040 und STM32 zeigt sich 1 ohne Warnung.
Vielen Dank, bei der Aktivierung -Wextra gibt es bei mir auch eine
Warnung.
Nun habei ich noch ein anderes Problem, vielleicht könnt ihr mir da auch
helfen:
Folgender Code liefert die Warnung:
signed and unsigned type in conditional expression
Kann ich das Problem besser lösen?
1
#define BV(bit) (1 << (bit))
2
#define bit_is_high(reg,bit) (((reg)&BV(bit))!=0)
3
#define vorzeichen_erweitern(x) (bit_is_high(x, 9) ? x | 0xFC00 : x)
Simon schrieb:> signed and unsigned type in conditional expression> Kann ich das Problem besser lösen?
Naja, entweder signed oder unsigned rechnen oder casten.
Ein ganz brauner "Trick": linksshiften um 6 und danach rechtsschiften
genauso viel. Dann brauchst Du kein If und keine defineorgien.
int16 tmp = ADC<<6;
tmp>>=6;
Bzw 3 bei typischen 12 Bit + Vorzeichen
Simon schrieb:> Kann ich das Problem besser lösen?
Jedenfalls nicht mit Makros.
Seit den 80ern sind schon ein paar Jahre ins Land gegangen.
Ansonsten halt mit cast ausdrücken, was man wie konvertiert haben will
anstatt es dem Compiler zu überlassen: will ich bei einem Vergleich
eines signed mit einem unsigned den Vergleich in signed oder in unsigned
haben? Entsprechend das eine oder andere konvertieren.
Simon schrieb:> Kann ich das Problem besser lösen?
Ersetze
1
x|0xFC00
durch
1
x-(1<<10)
Das gibt keine Warnung, weil alles in signed gerechnet wird, und
funktioniert auch, wenn x bzw. tmp mehr als 16 Bit breit ist.
Simon schrieb:> ps.: Ganz vergessen.> Der ADC liefert einen vorzeichenbehafteten 12Bit-Wert.
Sicher? bit_is_high(x, 9) und 0xFC00 sehen für mich eher nach 10 Bit
aus. Für 12 Bit wäre die Ersatzschreibweise
Frank M. schrieb:> Adam P. schrieb:>>> Jedoch gibt es eine Warning:>> "warning: comparison between signed and unsigned integer expressions>> [-Wsign-compare]">> Ich habs eben unter Linux getestet. Bei mir gibt es weder diese Warnung> noch den Fehler: Es wird "1" ausgegeben.> $ cc -O2 -Wall -Wextra a.c> $ ./a.out> 1> $ cc -v> ...> gcc version 8.3.0 (Debian 8.3.0-6)>> Wenn, dann muss es etwas avr-gcc-spezifisches sein - eventuell in einer> speziellen Compilerversion.
Ich würde es auf die integer Promotion schieben: bei arithmetischen
Operationen werden die Operanten implizit auf int gecastet, sofern ihr
Typ schmaler ist als int.
Auf den 32bit MCUs und dem PC ist das gegeben, auf dem AVR nicht.
Warum unsigned signed auf dem AVR „Vorrang“ gegeben wird, weiß ich
nicht, vielleicht ist es UB/IDB und deswegen die Warnung?
Simon schrieb:> Der ADC liefert einen vorzeichenbehafteten 12Bit-Wert.
Welcher ADC?
Bei einigen ADC's kann man konfigurieren was man braucht:
-binary
-binary offset
-2 complement
-gray
-1 complement
eine 'Vorzeichenbehaftete Codierung (signed) gibt es genau genommen bei
ADC's nicht, das heisst höchstens 'polar encoding', weil dem ADC ist es
wurscht wo du den 0-Punkt in das Analogintervall Min-Max setzt. Dem
C-Compiler dagegen nicht.
Yalu X. schrieb:> Das gibt keine Warnung, weil alles in signed gerechnet wird, und> funktioniert auch, wenn x bzw. tmp mehr als 16 Bit breit ist.>> Simon schrieb:>> ps.: Ganz vergessen.>> Der ADC liefert einen vorzeichenbehafteten 12Bit-Wert.>> Sicher? bit_is_high(x, 9) und 0xFC00 sehen für mich eher nach 10 Bit> aus. Für 12 Bit wäre die Ersatzschreibweise
Herzlichen Dank!
Du hast natürlich Recht; es ist ein 10 Biit ADC.
Gruß
Simon