mikrocontroller.net

Forum: Compiler & IDEs Fehlerhafter RETURN bei Optimierung


Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

könnt Ihr mit Tips geben woran folgendes liegen könnte:

Eine Funktion ruft eine andere auf -  diese ist relativ aufwändig und 
gibt dann mittels return etwas zurück  -  mit ausgeschalteter 
Optimierung geht das alles wunderbar  -  schalte ich die Optimierung 
ein, so springt das nach return Programm an eine beliebige ( immer 
gleiche) Stelle im Programm

Simulation in AVR-Studio
 Chip:  ATMEGA 8

ich würde mich sehr freuen  -  vielleicht ist es ein bekanntes Problem


Danke !

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

Bewertung
0 lesenswert
nicht lesenswert
Tommy wrote:
> Hallo,
>
> könnt Ihr mit Tips geben woran folgendes liegen könnte:
>
> Eine Funktion ruft eine andere auf -  diese ist relativ aufwändig und
> gibt dann mittels return etwas zurück  -  mit ausgeschalteter
> Optimierung geht das alles wunderbar  -  schalte ich die Optimierung
> ein, so springt das nach return Programm an eine beliebige ( immer
> gleiche) Stelle im Programm
>
> Simulation in AVR-Studio
>  Chip:  ATMEGA 8
>
> ich würde mich sehr freuen  -  vielleicht ist es ein bekanntes Problem
>

Welche Version willst du haben?
* Die Glaskugelvariante oder auch
  'Ich rate jetzt mal ins Blaue hinein' - Variante genannt:

  Wenn du Unordnung auf dem Stack erzeugst, dann kann sowas schon
  mal vorkommen. Immer noch beliebtes Werkzeug dazu, sind Array-
  Overflows. Diese können in Form von 'normalen' Arrays vorkommen
  oder aber, ganz beliebt, in Form von zu klein dimensionierten
  Arrays für Strings

* die vernünftige Variante:
  Es gibt tausend und einen Grund, wie sowas zustande kommen kann.
  Ohne Source Code kann man dazu gar nichts sagen.
  Deine Anfrage ist ungefähr so spezifisch wie:
  "Doktor, es tut weh! Was könnte das sein?"

Autor: Tommy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...ja ich suche ja auch nach meiner Kugel....

das einzige was der Compiler noch meldet :   Invalid opcode
0xffff at address 0x000f91

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tommy wrote:
> ...ja ich suche ja auch nach meiner Kugel....

Es reicht wenn du Sourcecode anhängst. Und zwar solchen, der möglichst 
klein ist, aber den Fehler reproduzierbar zeigt.

Autor: Tommy (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

vielen Dank für eure Hilfe  -  habe mal alles was nicht zum Fehler 
beiträgt gelöscht ....

daher macht das Programm jetzt nix sinnvolles mehr  -  aber bei dem 
Return kommt genau der Fehler vor  -  allerdings nur bei der Optimierung 
( also bei 00 nicht)

...die Funktion bla() wird nie erreicht ...

vielen Dank für eure Mühe !

Gruß

T.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal eine grobe Abschaetzung machen: Du hast zwei verschachtelte 
Schleifen, die aeussere mit 7, die innere mit 8 Durchlaeufen. Macht 
insgesamt 56 Durchlaeufe der inneren Schleife. n_shift wird jedesmal 
inkrementiert, ausser in genau drei Faellen. Macht 53 Inkrementierungen. 
n_pack wird demnach 6 Mal inkrementiert. Also nimmt n_pack die Werte 0, 
1, ..., 6 an. Problem: Das array paket hat keine 7 Elemente, aber du 
greifst auf paket[6] zu. Das zerstoert dir den Stack und damit die 
Ruecksprungadresse.

Btw, ich wuerde den Operatoren ein paar Leerzeichen spendieren. 
Langsamer wird es dadurch nicht, aber sowas wie
for(n_Hshift = 0; n_Hshift < 8; n_Hshift++)
ist IMHO einfach lesbarer als
for(n_Hshift=0;n_Hshift<8;n_Hshift++).

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

Bewertung
0 lesenswert
nicht lesenswert
Chris wrote:
> Mal eine grobe Abschaetzung machen: Du hast zwei verschachtelte
> Schleifen, die aeussere mit 7, die innere mit 8 Durchlaeufen. Macht
> insgesamt 56 Durchlaeufe der inneren Schleife. n_shift wird jedesmal
> inkrementiert, ausser in genau drei Faellen. Macht 53 Inkrementierungen.
> n_pack wird demnach 6 Mal inkrementiert. Also nimmt n_pack die Werte 0,
> 1, ..., 6 an. Problem: Das array paket hat keine 7 Elemente, aber du
> greifst auf paket[6] zu. Das zerstoert dir den Stack und damit die
> Ruecksprungadresse.

Ich bin immer noch fasziniert von deiner Analyse. Saubere
Arbeit!

Ach ja: Ein simples Durchsteppen durch den Code bestätigt:
n_pack wird tatsächlich zu 6. Da danach zumindest noch
ein paket[n_pack] = 0 erfolgt, sind alle Zutaten beisammen
um den Stack zu zerstören.

D.h. die Glaskugelvariante war doch nicht so schlecht :-)

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Chris wrote:
>> Mal eine grobe Abschaetzung machen: Du hast zwei verschachtelte
>> Schleifen, die aeussere mit 7, die innere mit 8 Durchlaeufen. Macht
>> insgesamt 56 Durchlaeufe der inneren Schleife. n_shift wird jedesmal
>> inkrementiert, ausser in genau drei Faellen. Macht 53 Inkrementierungen.
>> n_pack wird demnach 6 Mal inkrementiert. Also nimmt n_pack die Werte 0,
>> 1, ..., 6 an. Problem: Das array paket hat keine 7 Elemente, aber du
>> greifst auf paket[6] zu. Das zerstoert dir den Stack und damit die
>> Ruecksprungadresse.
>
> Ich bin immer noch fasziniert von deiner Analyse. Saubere
> Arbeit!

Echt nicht übel! ;)

Zum Problem: Jaja, der Klassiker, wie schon von Karl Heinz vermutet ;)

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wundere mich nur über diese Zeilen:

// ...

  !(n_Hpack | n_Hshift)

// ...

  if(!((position==8) | (position==16) | (position==32)))

// ...

und frage mich, ob der Verfasser sicher ist, dass dort das passiert was 
passieren soll? Komisch dass der Compiler nicht wenigstens bei der 
if-Abfrage eine Warnung schmeisst (habe es nicht getestet).

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

Bewertung
0 lesenswert
nicht lesenswert
die ??? wrote:
> Ich wundere mich nur über diese Zeilen:
>
>
>
> // ...
> 
>   !(n_Hpack | n_Hshift)
> 
> // ...
> 
>   if(!((position==8) | (position==16) | (position==32)))
> 
> // ...
> 
>
> und frage mich, ob der Verfasser sicher ist, dass dort das passiert was
> passieren soll?

Der erste Asudruck
   !(n_Hpack | n_Hshift)

ist equivalent zu

   n_Hpack != 0  &&  n_Hshift != 0

zusammen mit dem Kommentar in dieser Zeile, sieht das
durchaus so gewollt aus.

  n_Hpack | n_Hshift   liefert als bitweises Oder nur dann eine
0, wenn sowohl n_Hpack als auch n_Hshift 0 sind. Dieses Ergebnis
dann logisch umgedreht, liefert TRUE, wenn beide 0 sind.


> Komisch dass der Compiler nicht wenigstens bei der
> if-Abfrage eine Warnung schmeisst (habe es nicht getestet).

Warum sollte er?
Das sind ganze normale Ausdrücke. Entweder der Ausdruck evaluiert
zu 0 oder er tut es nicht.

>   if(!((position==8) | (position==16) | (position==32)))

Dich stört wahrscheinlich, dass hier bitweise Oder benutzt werden.
Macht aber in diesem konkreten Fall keinen Unterschied.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Der erste Asudruck
>    !(n_Hpack | n_Hshift)
>
> ist equivalent zu
>
>    n_Hpack != 0  &&  n_Hshift != 0
>
> zusammen mit dem Kommentar in dieser Zeile, sieht das
> durchaus so gewollt aus.
>
>   n_Hpack | n_Hshift   liefert als bitweises Oder nur dann eine
> 0, wenn sowohl n_Hpack als auch n_Hshift 0 sind. Dieses Ergebnis
> dann logisch umgedreht, liefert TRUE, wenn beide 0 sind.

Jau, als Stichwort: DeMorgansches Gesetze
http://de.wikipedia.org/wiki/De_Morgansche_Gesetze

Autor: Tommy B. (tommy1960)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DANKE !!!!!!!!!!!!!!!!!!!! Chris

.... au Mann  -  das darf nicht wahr sein  ....   SUPER DANKE an alle  - 
sorry, dass es so ein dummer Fehler war !!!!!!

schönen Abend !

Autor: Tommy B. (tommy1960)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hey super, prima funzt  -  hehe !


D A N K E ! ! ! ! !

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Dich stört wahrscheinlich, dass hier bitweise Oder benutzt werden.
> Macht aber in diesem konkreten Fall keinen Unterschied.

Macht es nicht? Für mich scheint das etwas inkonsistent:

if(!((position==8) | (position==16) | (position==32)))

Hier werden Ergebnisse aus einer logischen Operation mit Hilfe einer 
bitweisen Operation verknüpft. Wie gesagt, es wundert mich nur, dass 
nicht wenigstens eine Warnung kommt (nach dem Motto "ob der Anwender 
sich sicher sei dass es so gewollt ist") - kann sein dass C dort nicht 
so strikt ist wie mancher C++ Compiler ob des expliziten 
bool-Datentypes.
Die andere Zeile war soweit passabel, ich habe den Kommentar nicht 
gelesen - das muss ich mir endlich mal angewöhnen  ;-)  .

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

Bewertung
0 lesenswert
nicht lesenswert
die ??? wrote:

> Macht es nicht? Für mich scheint das etwas inkonsistent:

Erinnere dich:
In C gibt es erst mal keinen eignen bool Datentyp.

Alles was ein arithmetischer Ausdruck ist, kann auch
als logischer Ausdruck verwendet werden und umgekehrt.
0 wird zu false, alles ungleich 0 wird zu true


> if(!((position==8) | (position==16) | (position==32)))

> Hier werden Ergebnisse aus einer logischen Operation mit Hilfe einer
> bitweisen Operation verknüpft.

Ist kein Problem. Das Ergebnis einer logischen Operation ist auch
erst mal nur eine Zahl. Und mit der kann man auch rechnen :-)

  if( ( (position==8) + (position==16) + (position==32)) == 0)

würde genau dasselbe bewirken.

> Wie gesagt, es wundert mich nur, dass
> nicht wenigstens eine Warnung kommt (nach dem Motto "ob der Anwender
> sich sicher sei dass es so gewollt ist") - kann sein dass C dort nicht
> so strikt ist wie mancher C++ Compiler ob des expliziten
> bool-Datentypes.

Yep.

Autor: let (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  if( ( (position==8) + (position==16) + (position==32)) == 0)
>würde genau dasselbe bewirken.

Nur in C++. Dort ist das Ergebnis einer logischen Operation mit
0 oder 1 definiert. In C kann 'logisch 1' alles außer 0 bedeuten.
Das Ergebnis der Addition kann also zufällig 0 ergeben (Überlauf).

Durch solche Trickprogrammierungen stürzen Flugzeuge ab ;).

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
let wrote:

>>  if( ( (position==8) + (position==16) + (position==32)) == 0)
>>würde genau dasselbe bewirken.

> Nur in C++. Dort ist das Ergebnis einer logischen Operation mit
> 0 oder 1 definiert. In C kann 'logisch 1' alles außer 0 bedeuten.

Das ist Quatsch, sorry.

In C ist das Ergebnis einer logischen Operation genauso definiert
wie in C++.  Wenn ein Compiler für 0 == 0 etwas anderes als den
Wert 1 generiert, dann hat er nicht das Recht, sich C-Compiler zu
nennen.

Wenn du's nicht glaubst, grabe ich dir auch die passende Stelle des
Standards raus, bin aber gerade zu faul dazu.

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

Bewertung
0 lesenswert
nicht lesenswert
let wrote:

Jörg hat sich ja zum Rest schon geäußert.

> Durch solche Trickprogrammierungen stürzen Flugzeuge ab ;).

Meine absolute, 100%-ige, aus tiefstem Herzen kommende,
durch nichts zu beirrende, absolute (sagte ich das schon?)
                Z U S T I M M U N G.


Ich hab das Beispiel nicht gebracht, damit jemand so programmiert,
sondern nur um zu zeigen, dass:

  Compiler gibt keine Warnung oder Fehler

nicht notwendigerweise irgendetwas heißen will. Oder wie
jemand anderer in grauer Vorzeit sagte:
Ein guter Programmierer kann in jeder Sprache Fortran programmieren.

Autor: let (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn du's nicht glaubst, grabe ich dir auch die passende Stelle des
>Standards raus, bin aber gerade zu faul dazu.
Wenn du das sagst wird es wohl stimmen. Aber war das schon zu ANSI
Zeiten so? Irgendwo habe ich nämlich vor langer Zeit in einer
Gegenüberstellung (Stroustrup?) zwischen C/C++ gelesen das besagtes
Ergebnis jetzt (c++ - das ja C ersetzen sollte) genau definiert ist.
Obwohl die meisten Compiler das ohnehin so tun würden.

Autor: let (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habs gerade in der Bibel nachgeschlagen: Die Regel kannte ANSI
auch schon. Da habe ich mir wohl etwas zurechtgesponnen.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  if( ( (position==8) + (position==16) + (position==32)) == 0)

Ok, welcher Datentypen wird hier für die logischen Ergebnisse 
angenommen? Signed 16Bit? Ich gehe davon aus. Lasst mich etwas spinnen: 
Angenommen diese Abfrage enthält genau soviele Vergleiche, dass es zu 
einem Überlauf kommen kann der das Ergebnis 0 liefert wenn alle 
Vergleiche wahr/'true' sind.

  (0) == 0

Blöd.

Ist nicht das gleiche wie

  if( ( (position==8) | (position==16) | (position==32)) == 0)

da es hier niemals zu einem Überlauf kommt wenn der Compiler auf

  (0 == 0) := 1

besteht. Karl, du hast den Kopf aus der Schlinge gezogen weil du 
geschrieben hast "genau dasselbe bewirken". Trotzdem bestehe ich auf

#ifndef FALSE
  #define FALSE (1 == 0)
#endif

  if( ((position==8) || (position==16) || (position==32)) == FALSE )

um unnötige Diskusionen wie diese hier zu vermeiden  ;-)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die ??? wrote:

> Ok, welcher Datentypen wird hier für die logischen Ergebnisse
> angenommen? Signed 16Bit?

`int', per definitionem.

> Angenommen diese Abfrage enthält genau soviele Vergleiche, dass es
> zu einem Überlauf kommen kann der das Ergebnis 0 liefert wenn alle
> Vergleiche wahr/'true' sind.

Hmm, das wären dann wenigsten 65536 Vergleiche (die alle wahr sein
müssen), die Zeile möchte ich mal sehen. :-)

> Trotzdem bestehe ich auf
#ifndef FALSE
  #define FALSE (1 == 0)
#endif

Was kompletter Unsinn ist.  Die Argumentation dafür spare ich mir, die
kannst du dir in der comp.lang.c-FAQ (bzw. in der de.comp.lang.c-FAQ)
durchlesen.

Bei C99 ist es sowieso sinnvoller, gleich
#include <stdbool.h>

zu nehmen, dann sind true und false (in dieser Schreibweise)
vordefiniert, und bool ein eigener Datentyp.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, so drastisch wie du drücken sich die FAQ's nicht aus, aber egal. 
Ich wusste nicht, dass bool mittlerweile dazu gehört. Danke für den 
Tip - wieder was gelernt!

Dann bestehe ich halt hierauf:

#include <stdbool.h>

// ...

  if( ((position==8) || (position==16) || (position==32)) == false )

;-)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Selbst das ist nicht sinnvoll.  Das Teil ist schon bool, und damit
hervorragend als Steuerausdruck eines if geeignet:
if( !((position==8) || (position==16) || (position==32)))
...

Kann man nach Boole's Regeln auch umschreiben als
if(position != 8 && position != 16 && position != 32)
...

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> Selbst das ist nicht sinnvoll.

Warum verallgemeinerst du so strikt?

 == false

Was ist daran "nicht sinnvoll" den Code lesbar zu gestalten?

  http://www.gnu.org/prep/standards/standards.html
  http://www.phaedsys.demon.co.uk/chris/papers/qa2tilehill.pdf

Solche Vereinfachungen darf dann der Compiler übernehmen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die ??? wrote:

> Was ist daran "nicht sinnvoll" den Code lesbar zu gestalten?

Ein Boolescher Ausdruck wird nicht ,,noch Boolescher'', indem man
einen Vergleich auf true oder false einbaut.  Er ist bereits
ein Wahrheitswert, ,,noch wahrer'' kann er nicht werden.  Dabei
ist der Vergleich
==false
 noch relativ harmlos, während
der analoge Vergleich
==true
 komplett hinkt und voll nach
hinten losgehen kann, falls nicht alle Teilausdrücke (so wie hier)
tatsächlich bereits Booleschen Charakter haben (also wirklich nur
true oder false als mögliche Werte).

Lesbarer wird er, indem man die Booleschen Regeln anwendet und
die zweite Form statt der ersten nimmt.  Das ist nicht nur eine
Vereinfachung (im Sinne der Optimierung), sondern einfach eine
Form, in der der mitlesende Mensch den gleichen Ausdruck besser
versteht: statt erst eine Liste von Gleichheiten aufzuzählen und
diese dann zu negieren, lieber gleich eine Liste von Ungleichheiten
aufzählen.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> komplett hinkt und voll nach hinten losgehen kann

Wir schweifen ab, wie so oft hier. Am Anfang ging es um | vs ||. Jetzt 
werden wieder Phrasen gedroschen ohne Beispiele zu bringen.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Was ist daran "nicht sinnvoll" den Code lesbar zu gestalten?
>
> Ein Boolescher Ausdruck wird nicht ,,noch Boolescher'', indem man
> einen Vergleich auf true oder false einbaut.

Man könnte ja auch schreiben:
  if (((true == ((position==8) || (position==16) || (position==32))) != false)

Schließlich will man ja wissen, ob es nicht falsch ist, daß es wahr ist, 
daß position == 8 oder == 16 oder == 32 ist. Oder will man wissen ob es 
wahr ist, daß es nicht falsch ist, daß es war ist, daß ...

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

Bewertung
0 lesenswert
nicht lesenswert
Du willst ein Beispiel.

Zunächst mal sei gesagt, dass bei sorgfältiger Programmierung
solche Vergleiche zwar oft unnötig aber auch nicht gefährlich
sind. Erst dann, wenn der Schlendrian zuschlägt, wirds gefährlich.

das

  if( a > b )

dasselbe ist wie

  if( ( a > b ) == true )

dürfte einleuchten.

Das aber

  if( a )

nicht dasselbe ist wie

  if( ( a ) == true )

dürfte auch klar sein. Man kann also nicht einfach nur einen
Ausdruck hernehmen, ein '== true' dahinterschreiben und denken,
dass sich dadurch schon nichts ändert.
Interessanterweise geht das aber in die umgekehrte Richtung
meistens aber gut


  if( !b )

und

  if( ( b ) == false )

sind tatsächlich in den meisten Fällen austauschbar. Zumindest fällt
mir jetzt auf die Schnelle kein Gegenbeispiel ein.

Die Kunst beim Programmieren besteht nicht darin,
 * alles so kurz wie nur irgendmöglich zu schreiben
 * alles so langatmig wie nur irgendmöglich zu schreiben
Die Kunst besteht darin, den richtigen Spagat zwischen den
beiden Extremen zu finden.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ist es Karl.

Wenn man jedoch einen Datentyp ungleich bool mit expliziten boolschen 
Abfragen attackiert wird es ohnehin inkonsitent. Oder irre ich? Warum 
wirft der GCC eigentlich keine Warnung (auch nicht mit -pedantic) wenn 
man

  #include <inttypes.h>
  #include <stdbool.h>

  / ...

  uint8_t x = 0;

  if( x == true )

  / ...

anführt? Ich gebe zu, dass ich mich darüber bisher nicht weiter 
informiert habe.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist einfach gültiges C, und absolut nichts, was es zu warnen gäbe.
bool ist als enum implementiert, und in C ist ein enum nichts anderes
als ein int.

In C++ sieht die Sache sehr viel anders aus.

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

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> Es ist einfach gültiges C, und absolut nichts, was es zu warnen gäbe.
> bool ist als enum implementiert, und in C ist ein enum nichts anderes
> als ein int.

Yep.
Das fällt für mich in die selbe Kategorie, wie dieses unselige
void foo( int bar[] )
{
 ...
}

Hier wird (in meinen Augen) etwas vorgetäuscht, was so einfach nicht
stimmt, nämlich die Übergabe eines Arrays. Erfahrene Programmierer
wissen was wirklich dahinter steckt, aber Neulinge fallen da
reihenweise hinein.

Da diese Schreibweise absolut identisch ist zu
void foo( int * bar )
{
 ...
}

frage ich mich ehrlich, wozu diese alternative Syntax gut sein soll.

Selbiges mit bool. Das ist doch reine Augenauswischerei. Ein bool
ist in C ein int. Mit etwas abweichender Schreibweise, aber
letztendlich ist das nur ein int. Und boolsche Ausdrücke funktionieren
für jemanden der neu zu C kommt nun mal nicht so wie er es erwarten
würde (vor allem wenn er bereits eine andere Sprache kennt).

  bool b = 5;

ist absolut legales, korrektes C. Das liegt sicherlich zunächst mal
daran, wie C mit enums umgeht, die in C ja nun wirklich ein ziemlicher
Bastard sind. Ähnlich wie die Arraysntax da oben sind sie eigentlich
zu nichts gut. Sie haben höchstens einen dokumentarischen Wert.
Ein
  void SetColor( enum Color col );
Prototyp erzählt mir als Leser nunmal mehr als
  void SetColor( int col );

Auf der anderen Seite verhindert er aber nicht, dass ich einen
Aufruf ala
  SetColor( 5 );
mache. Sicherheitstechnisch gesehen also eine absolute Katastrophe.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Jungs! Dann werde ich die stdbool.h wieder schleunigst 
vergessen, das ist wirklich Käse und gaukelt tatsächlich falsche 
Tatsachen vor. Da mir das nicht klar war haben wir etwas aneinander 
vorbei geredet; Ich dachte, dass man sich an C++ orientiert hat - schade 
dass dem nicht so ist.




P.S.
void foo( int bar[] )
{
 ...
}

Finde ich manchmal der Übersicht halber angenehm wenn man daran erinnern 
will, dass das Ziel der Adresse ein Array ist. Natürlich gehört das 
ordentlich Kommentiert. Geschmacksfrage.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Selbiges mit bool. Das ist doch reine Augenauswischerei. Ein bool
> ist in C ein int.

Nein! Zumindest nicht der aus stdint.h. Der ist ein typedef für _Bool, 
und das ist zwar im Prinzip so wie ich das sehe ein Integer, der aber 
explizit nur die Werte 0 und 1 kennt.

>  bool b = 5;
>
> ist absolut legales, korrektes C.

Das wäre aber auch in C++ korrekt. Das Resultat ist auch dasselbe. Der 
Wert von b entspricht nachher true (welche in C einfach als 1 #definiert 
ist).

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Zumindest nicht der aus stdint.h. Der

Sorry, meinte natürlich stdbool.h

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, einen Vorteil haben enums (und damit auch die aus stdbool.h):
der Debugger kann mit ihren Werten umgehen.  Statt 0 und 1 zeigt
er also brav false und true an.

Ein zweiter minimaler Vorteil ist, dass der GCC bei einem
switch mit einem enum als Steuerausdruck warnt, wenn bestimmte
im enum definierte Werte vom switch nicht abgedeckt werden.
(Ist natürlich für bool/true/false eher nicht der Fall.)

stdbool.h hat den zusätzlichen Vorteil, dass man zumindest all
diese privaten Definitionen von TRUE und FALSE damit in die Tonne
kloppen kann.  Wenn jemand die nicht haben will und sowieso schon
immer mit 0 und 1 dafür gearbeitet hat: fein.  Aber wer bisher
irgendwelche teilweise haarsträubend umständlich anmutende
Konstrukte für seine eigenen Definitionen von TRUE und FALSE
benutzt hat, der sollte stattdessen ernsthaft das standardisierte
true und false benutzen.

Ansonsten ist es wahr, enums sind in C ziemlich stiefmütterlich
behandelt.

Autor: let (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
_Bool ist kein enum. Ein enum hat normalerweise >= 16Bit, _Bool hat
gewöhnlich 8Bit. Außerdem wird bei einer Umwandlung nach _Bool
ein logischer Vergleich durchgeführt.

Im C99 Draft heißt es:

6.3.1.2 Boolean type
1 When any scalar value is converted to _Bool, the result is 0
if the value compares equal to 0; otherwise, the result is 1.

Der avr-gcc hält sich auch daran:
#include <stdbool.h>
#include <stdint.h>

extern bool bValue;
extern uint8_t u8Value;

int main()
{
  bValue = u8Value;
  u8Value = bValue;

  return 0;
}
00000092 <main>:
  92:  80 91 60 00   lds  r24, 0x0060
  96:  81 11         cpse  r24, r1
  98:  81 e0         ldi  r24, 0x01  ; 1
  9a:  80 93 61 00   sts  0x0061, r24
  9e:  80 93 60 00   sts  0x0060, r24

u8Value wird anschließend entweder 0 oder 1 enthalten.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Naja, einen Vorteil haben enums (und damit auch die aus stdbool.h):

Nochmals: stdbool.h hat NICHTS mit enums zu tun. Es definiert vier 
Makros:

#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1

(bei gcc fehlt der letzte Eintrag). Und _Bool ist ebenfalls kein enum, 
sondern ein eingebauter Typ, der nur die Werte 0 und 1 annehmen kann.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:

> Und _Bool ist ebenfalls kein enum,
> sondern ein eingebauter Typ, der nur die Werte 0 und 1 annehmen kann.

OK, wieder was gelernt.  Der Debugger stellt es als enum dar, daher
hatte ich mich nie näher um die Details gekümmert.

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.