Forum: Compiler & IDEs Negation in if Abfrage => Problem


von Matthias (Gast)


Lesenswert?

Warum wird folgender Ausdruck NIE wahr??
1
if ( ~PINC == 0xFF )
2
{
3
...
Der Compiler (-Os) macht daraus folgenden Unsinn:
WOzu muss das in 16bit gerechnet werden?? Da der hier das höherwertige 
Byte (wo auch immer er das hernimmt) mit Null initialisiert und auf 0xFF 
vergleicht, wirds nie wahr. ABER WARUM??
1
IN      R24,0x13         In from I/O location
2
CLR     R25              Clear Register
3
SUBI    R24,0x00         Subtract immediate
4
SBCI    R25,0xFF         Subtract immediate with carry
5
BRNE    PC-0x3B          edit: springe, wenn NICHT wahr


Mache ich es allerdings so, dann geht es:
1
variable = ~PINC;
2
if ( variable == 0xFF )
3
{
4
...
Das erzeugt:
1
LDS     R24,0x0100       Load direct from data space
2
CPI     R24,0xFF         Compare with immediate
3
BRNE    PC-0x3A          edit: springe, wenn NICHT wahr

von Florian D. (code-wiz)


Lesenswert?

Weil ~PINC in der Bedinung zu int (das sind bei Dir 16 Bit) wird.

if ( ~PINC == 0xFFFF )

sollte funktionieren, ist aber vermutlich Quatsch wegen des zusätzlichen 
Bytes.

von Andreas K. (a-k)


Lesenswert?

In C werden per Standard alle Operanden kleiner als "int" auf "int" 
erweitert, dann erst weiterverarbeitet. Zumindest muss das Ergebnis 
dieser Vorschrift entsprechen. Und genau das passiert hier, ~0 ist auf 
einer 16bit Maschine eben 0xFFFF, nicht 0xFF.

Freilich gibt es für Microcontroller etliche Compiler, die sich per 
Voreinstellung nicht an diese Regel halten, um kürzeren Code zu 
erhalten. Das widerspricht dann allerdings klar dem ANSI-C-Standard.

von Matthias (Gast)


Lesenswert?

ALso wird die 16bit-Regel in meinem funktionierenden Code deshalb nicht 
angewendet, weil ich diese temporäre Variable explizit mir uint8_t 
deklariert habe??

Danke soweit für die Antworten

von Andreas K. (a-k)


Lesenswert?

Ja.

von yalu (Gast)


Lesenswert?

Wieso schreibst du nicht einfach
1
if(PINC==0)
?

von Matthias (Gast)


Lesenswert?

Ja, könnte ich.
Ich wollte damit aber klarmachen, dass die angeschlossenen DIP-Schalter 
am PORTC nach Masse geschaltet sind, und somit negiert werden müssen

von Andreas K. (a-k)


Lesenswert?

Dann
1
if ( (PINC^0xFF) == 0xFF )

von Anonymus (Gast)


Lesenswert?

müsste es nicht auch so gehen ?

if (PINC == ~0xFF)

von UBoot-Stocki (Gast)


Lesenswert?

Hi,

dies mal aus den gcc-FAQs 
(http://sigterm.de/projects/sens-o-nuts/Dokumentation/atmel/libc/FAQ.html)

"Why does the compiler compile an 8-bit operation that uses bitwise 
operators into a 16-bit operation in assembly?
Bitwise operations in Standard C will automatically promote their 
operands to an int, which is (by default) 16 bits in avr-gcc.

To work around this use typecasts on the operands, including literals, 
to declare that the values are to be 8 bit operands.

This may be especially important when clearing a bit:


var &= ~mask;  /* wrong way!

The bitwise "not" operator (~) will also promote the value in mask to an 
int. To keep it an 8-bit value, typecast before the "not" operator:


var &= (unsigned char)~mask;"

Das müsste doch auch Dein Problem sein ... ?

Gruß

Andreas



von Andreas K. (a-k)


Lesenswert?

~0xFF = ~0x00FF = 0xFF00.

von Matthias (Gast)


Lesenswert?

Ja, genau darum gehts. Scheiß Standart ;-)

aber bei:

PORTC   &=   ~(1<<PORTC2);

bleibts doch auch bei 8bit...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das ist ja auch eine Zuweisung, kein Vergleich.


Was aber hat das mit der Art des Stehens zu tun?

von Andreas K. (a-k)


Lesenswert?

Wo ist da dein Problem? Das ist doch
1
PORTC &= ~(1<<2);
2
PORTC &= ~4;
3
PORTC &= 0xFFFB;
und der Compiler weiss, dass dies als Bit-Operation zum gleichen 
Ergebnis führt wie
1
PORTC = (int)PORTC & 0xFFFB;
Entscheidend ist was hinten rauskommt (Zitat). Wenns 8bittig das gleiche 
ist wie 16bittig, darf er optimieren.

Nur hattest du oben ein Beispiel erwischt, wo es nicht egal ist. Ein 
anderer Fall, wo es nicht egal ist ob mit 8 oder 16 Bits gerechnet:
1
unsigned char n;
2
if (n+1 < 100)
3
  ...

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.