mikrocontroller.net

Forum: Compiler & IDEs Inhalt vom Byte checken?


Autor: tobiTob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich wollte mit der folgenden Funktion 1 oder 0 zurück bekommen.
Ich dachte es sei 1 wenn chkbyte eben nicht in die Anforderung passt.

Hmm kommt aber immer 0 raus, egal was ich für einen Wert übergebe, was 
hab ich da übersehen?
uint8_t chk_byte(char chkbyte){
  return (((chkbyte >= 30) && (chkbyte <= 128)) && (chkbyte != 45) && (chkbyte != 90));
}

Gruß Tobi...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(chkbyte != 45) && (chkbyte != 90));

Für jede beliebige Zahl gilt:
Da sie nicht gleichzeitig 45 und gleichzeitig 90 sein kann,
gilt für jede Zahl: sie ist entweder nicht 45 oder nicht gleich
90.
D.h. einer der beiden Teilausdrücke ist immer falsch und damit
ist die UND-Verknüpfung auch immer falsch.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> (chkbyte != 45) && (chkbyte != 90));
>
> Für jede beliebige Zahl gilt:
> Da sie nicht gleichzeitig 45 und gleichzeitig 90 sein kann,
> gilt für jede Zahl: sie ist entweder nicht 45 oder nicht gleich
> 90.
> D.h. einer der beiden Teilausdrücke ist immer falsch und damit
> ist die UND-Verknüpfung auch immer falsch.
Hmmm... (chkbyte != 45) ist nur dann falsch (0), wenn chkbyte 45 ist.
(chkbyte != 90) ist nur dann falsch (0), wenn chkbyte 90 ist.
Wenn chkbyte WEDER 45 NOCH 90 ist, müssten doch eigentlich beide 
Ausdrücke eine 1 zurückliefern (und ich denke, das ist das, was der OP 
will), oder hab ich was übersehen?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> (chkbyte <= 128)
Fällt mir noch grad auf: char hat einen Wertebereich von -128...+127. 
Der Check auf <= 128 kann fürchterlich in die Hose gehen! Ich weiß jetzt 
zwar nicht, was der Compiler daraus macht, aber das solltest Du 
vielleicht ändern. Kommen überhaupt negative Werte vor? Wenn nicht, dann 
besser mit unsigned char bzw. uint8_t...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das sollte eigentlich keine Probleme machen. Der Compiler ignoriert dann 
einfach den Vergleich auf <= 128, weil das Ergebnis sowieso immer wahr 
ist. Eigentlich müßte gcc auch eine entsprechende Warnung ausgeben.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:
> Eigentlich müßte gcc auch eine entsprechende Warnung ausgeben.
Du weißt doch, wie das mit den Warnungen ist: Die liest eh keiner...;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Karl heinz Buchegger wrote:
>> (chkbyte != 45) && (chkbyte != 90));
>>
>> Für jede beliebige Zahl gilt:
>> Da sie nicht gleichzeitig 45 und gleichzeitig 90 sein kann,
>> gilt für jede Zahl: sie ist entweder nicht 45 oder nicht gleich
>> 90.
>> D.h. einer der beiden Teilausdrücke ist immer falsch und damit
>> ist die UND-Verknüpfung auch immer falsch.
> Hmmm...

Auch hmm.

Du hast recht.
Immer diese komplizierten Logik Ausdrücke und De Morgan, etc.

Aber warum ist das dann trotzdem immer falsch?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:

> Aber warum ist das dann trotzdem immer falsch?

Ist es doch gar nicht!

Ein kleines Testprogramm
uint8_t chk_byte(char chkbyte){
  return (((chkbyte >= 30) && (chkbyte <= 128)) && (chkbyte != 45) && (chkbyte != 90));
}

int main()
{
  uint8_t i;

  for( i = 0; i < 128; ++i )
    printf( "%d %d\n", i, chk_byte(i));
  return 0;
}

zeigt das Verhalten, von dem ich denke, dass der OP es haben
möchte.

ALso: tobiTob

Welches Verhalten ist gewünscht?
Wie hast du kontrolliert, dass der Ausdruck
nicht so funktioniert, wie du dir das vorstellst?

Autor: tobiTob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

danke für die Antworten...

Ich habe die Werte 0, 32 und 255 übergeben.

Gültig sind aber nur Werte die >30 und <128 sind aber nicht "nicht" 45 
und  "nicht" 90.

Ich schau mal eben gerade nochmal, vlt. hab ich mich doch vertan...


Gruß Tobi...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tobiTob wrote:
> Gültig sind aber nur Werte die >30 und <128 sind aber nicht "nicht" 45
> und  "nicht" 90.

Vorsicht mit doppelten Verneinungen und 'und' und 'oder'.

Ich vermeide eigentlich solch komplizierte Ausdrücke und
programmiere das aus:
uint8_t chk_byte(char chkbyte){
  if( chkbyte < 30 || chkbyte > 128 )
    return 0;

  if( chkbyte == 45 )
    return 0;

  if( chkbyte == 90 )
    return 0;

  return 1;
}

So kann ich auch nach 2 Jahren noch auf einen Blick sehen,
unter welchen Bedingungen eine Zahl den Test passieren kann.

Autor: tobiTob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:-O

Sorry es lag an der eigendlichen Auswertung, sowas aber auch... ;-)
if (chk_byte(ram_sp.runmode) != 0) {
ram_sp.runmode=23;
}

nun nimmt man == 0 dann geht's... was nun auch logisch ist...

War das ja garnicht so falsch was man da gebraut hat...

Kann man das in der chk_byte funktion evtl. "drehen" ?

Gruß Tobi...

Ohh sehe gerade den Zusatz... ja ich denke das werde ich wohl auch 
machen... ich teste das mal, das zuviel kürzen ist vlt. nicht immer 
Sinnvoll...

TNX!

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kann man das in der chk_byte funktion evtl. "drehen" ?

Ja, indem du jeden Teilausdruck invertierst und aus UND ein ODER machst:
return chkbyte < 30 || chkbyte > 128 || chkbyte == 45 || chkbyte == 90;

Autor: Detlef _a (detlef_a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei mir funzt Tobis Code auch. Hat meiner Ansicht was mit 'Char' zu tun: 
128 passt in nen signed char nich rein, in nen unsigned ja. Beim 
Vergleich mit '128' läuft vermutlich was schief. Ob char default 
unsigned oder signed ist läßt sich mit nem Compilerswitch manchmal 
einstellen.

Cheers
Detlef

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ob char default unsigned oder signed ist läßt sich mit nem
> Compilerswitch manchmal einstellen.

Das verstellt man aber am besten nicht, sondern benutzt, wenn's drauf 
ankommt, immer explizit entweder signed char oder unsigned char.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:
>> Ob char default unsigned oder signed ist läßt sich mit nem
>> Compilerswitch manchmal einstellen.
>
> Das verstellt man aber am besten nicht, sondern benutzt, wenn's drauf
> ankommt, immer explizit entweder signed char oder unsigned char.
...und zumindest für "normale" Rechenvariablen besser (u)int8_t. Da 
gibts nämlich keinen Compiler-Switch den man "versehentlich" verstellen 
kann.

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.