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.