www.mikrocontroller.net

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


Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum wird folgender Ausdruck NIE wahr??
if ( ~PINC == 0xFF )
{
...
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??
IN      R24,0x13         In from I/O location
CLR     R25              Clear Register
SUBI    R24,0x00         Subtract immediate
SBCI    R25,0xFF         Subtract immediate with carry
BRNE    PC-0x3B          edit: springe, wenn NICHT wahr


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

Autor: Florian Demski (code-wiz)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja.

Autor: yalu (Gast)
Datum:

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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann
if ( (PINC^0xFF) == 0xFF )

Autor: Anonymus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
müsste es nicht auch so gehen ?

if (PINC == ~0xFF)

Autor: UBoot-Stocki (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

dies mal aus den gcc-FAQs 
(http://sigterm.de/projects/sens-o-nuts/Dokumentati...)

"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



Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
~0xFF = ~0x00FF = 0xFF00.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, genau darum gehts. Scheiß Standart ;-)

aber bei:

PORTC   &=   ~(1<<PORTC2);

bleibts doch auch bei 8bit...

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ja auch eine Zuweisung, kein Vergleich.


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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist da dein Problem? Das ist doch
PORTC &= ~(1<<2);
PORTC &= ~4;
PORTC &= 0xFFFB;
und der Compiler weiss, dass dies als Bit-Operation zum gleichen 
Ergebnis führt wie
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:
unsigned char n;
if (n+1 < 100)
  ...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.