GCC legt ein merkwürdiges Verhalten an den Tag, wenn es um Nicht-ASCII-Zeichen bei Zuweisung auf uint8_t geht. Im folgenden Testprogramm wird die Abfrage "if (Zeich=='§') .." komplett ignoriert, ohne eine Warnung auszugeben. GCC 4.1.2 (WinAVR-20070525) gibt hier wenigstens eine Warnung aus: ../Test.c:14: warning: comparison is always false due to limited range of data type trotzdem ist das Verhalten nicht befriedigend, denn in beiden Versionen wird das "§"-Zeichen als einfaches 0xA7 codiert. Codebeispiel: #include <string.h> #include <stdlib.h> #include <avr/io.h> #include <avr/pgmspace.h> prog_char Zeichen[] = {'#','§','+'}; uint8_t Zeich; int main(void) { Zeich = PORTB; if (Zeich=='#') Zeich = 1; if (Zeich=='§') Zeich = 1; PORTC = '§'; return Zeich; } Ausschnitt aus Makefile PROJECT = Test MCU = atmega168 TARGET = Test.elf CC = avr-gcc.exe ## Options common to compile, link and assembly rules COMMON = -mmcu=$(MCU) ## Compile options common for all C compilation units. CFLAGS = $(COMMON) CFLAGS += -Wall -gdwarf-2 -std=gnu99 -DF_CPU=18432000UL -Os ##CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums ##CFLAGS += -fno-inline -mcall-prologues -Wno-main ##CFLAGS += -fno-inline -Wno-main ##CFLAGS += -fno-inline-small-functions ausschnitt aus lss-File: 00000068 <Zeichen>: 68: 23 a7 2b 00 #.+. .. 00000094 <main>: prog_char Zeichen[] = {'#','§','+'}; uint8_t Zeich; int main(void) { Zeich = PORTB; 94: 85 b1 in r24, 0x05 ; 5 96: 80 93 00 01 sts 0x0100, r24 ; -> Zeich if (Zeich=='#') Zeich = 1; 9a: 83 32 cpi r24, 0x23 ; 35 9c: 19 f4 brne .+6 ; 0xa4 <main+0x10> 9e: 81 e0 ldi r24, 0x01 ; 1 a0: 80 93 00 01 sts 0x0100, r24 ; -> Zeich if (Zeich=='§') Zeich = 1; PORTC = '§'; a4: 87 ea ldi r24, 0xA7 ; 167 a6: 88 b9 out 0x08, r24 ; 8 return Zeich; } a8: 80 91 00 01 lds r24, 0x0100 ; -> Zeich ac: 90 e0 ldi r25, 0x00 ; 0 ae: 08 95 ret 000000b0 <_exit>: b0: f8 94 cli 000000b2 <__stop_program>: Harald
Mache Dich bitte mit den Feinheiten von signed und unsigned vertraut; dann verstehdt Du, was in Deiner Logik fehlerhaft ist. Bernhard
Bernhard R. schrieb: > Mache Dich bitte mit den Feinheiten von signed und unsigned vertraut; > dann verstehdt Du, was in Deiner Logik fehlerhaft ist. @Harald und ganz wichtig: mit den Feinheiten der int-Promotion Regel. Die Details dazu müsstest du in deinem C-Buch finden.
1 | int foo (unsigned char x) |
2 | {
|
3 | return x == '§'; |
4 | }
|
avr-gcc foo.s -S -Wextra
1 | zeich.c: In function 'foo': |
2 | zeich.c:4:5: warning: comparison is always false due to limited range of data type [-Wtype-limits] |
Die Warnung muss man aktivieren, sonst bekommt man sie natürlich nicht... Das Zeichen ist ein char und damit vorzeichenbehaftet, im vorliegenden Falle also negativ — es sei denn, du magst -funsigned-char. Ich sehe nur die "böse" Falle nicht. Aber die schlimmsten Fallen sind ja die, die man sich selber gräbt ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.