Hallo zusammen,
leider enthält ja avr-gcc kein stdbool.h (wieso eigentlich nicht?
stdint existiert ja auch...).
Mir ist beim Ausmisten eines alten Projektes gerade aufgefallen dass ich
dort stdbool benutze. Mein Eclipse kann mir den include auch auflösen,
es wird die aus der "normalen" gcc Installation verwendet!
Ist natürlich gefährlich, auf Systemen ohne gcc (Windows).
Woher holt ihr denn eure boolschen Typen? Einfach selber einen Header
schreiben? Wie genau definiert ihr boolean, TRUE und FALSE?
Groß-/Kleinschreibung? Boolean oder Bool?
Oder einfach die stdbool abtippen und ins Projektverzeichnis kopieren?
Zugegeben, ist eher ne Frage aus Neugier denn ein technisches Problem
:-)
Grüße und schönen Abend noch
Also unter Windows mit Atmel Studio 6.1 muss ich gar nichts includieren
um
1
booltest_var=false;
zu benutzen.
Henry schrieb:> leider enthält ja avr-gcc kein stdbool.h (wieso eigentlich nicht?
Vielleicht ist das mal wo anders mit rein gewandert bzw. ist jetzt
build-in.
Um
1
int
zu benutzten musst du ja auch nichts extra einbinden.
Gruesse
Weil stdbool.h gefährlich ist.
_Bool ist der reale boolean type.
1 The header <stdbool.h> defines four macros.
2 The macro
bool expands to _Bool.
3 The remaining three macros are suitable for use in #if
preprocessing directives. They are
true : which expands to the integer constant 1,
false: which expands to the integer constant 0, and
__bool_true_false_are_defined which expands to the integer
constant 1.
4 Notwithstanding the provisions of 7.1.3, a program may undefine
and perhaps then redefine the macros bool, true, and false.
Früher hatte man true/false so definiert:
#define false (0!=0)
#define true (0==0)
oder auch
#define true !false
Die C99 Definition ist aber 1 und 0
wenn du dann stdbool.h nimmst, dann wird folgender code niemals
ausgeführt.
angenommen events_mask ist 0xfc
if (events & events_mask == true) {
...
}
wenn du aber nach der alten Norm programmierst, funktioniert der code,
weil dann (events&events_mask) in _bool convertiert wird und dann
verglichen wird, weil true _bool ist, hingegen C99 true ist integer 1.
Weil dies in C++ nicht passiert, weil type enforcement dort herrscht,
ist dies anfänglich nicht aufgefallen, und später war der Schaden schon
da.
Pascal hält sich halt lange, denn true/false ist pascal , in realem C
würde man einfach if(events & events_mask) schreiben, aber es stimmt,
true / false erhöht wirklich die Lesbarkeit des Codes.
chris schrieb:> Weil stdbool.h gefährlich ist.
Das ist so pauschal doch Unsinn.
> _Bool ist der reale boolean type.
Ja, oder bool aus <stdbool.h>. Und ja, das gibt es beim AVR-GCC.
> angenommen events_mask ist 0xfc>> if (events & events_mask == true) {> ...> }>> wenn du aber nach der alten Norm programmierst, funktioniert der code,> weil dann (events&events_mask) in _bool convertiert wird und dann> verglichen wird, weil true _bool ist, hingegen C99 true ist integer 1.
Wer so etwas programmiert, der hat nichts anderes verdient. Es wird eine
Bitoperation ausgeführt, dessen Ergebnis ebenfalls wieder von einem
Integer Datentypen ist. Warum sollte man einen Integer mit einem
boolschen Wert vergleichen wollen?
#define TRUE 1
#define FALSE 0
Und ein Boolean wird per typedef aus einem uint8 "gewonnen". Dabei muss
man aber aufpassen, dass man wirklich nur mit TRUE und FALSE arbeitet.
1
Booleanflag=TRUE;
2
if(flag==TRUE)
3
...
Ich mache den Vergleich bei if-Anweisungen immer, auch wenn sie gerade
bei Flags nicht immer benötigt werdn. Der Vorteil ist zu einem die
bessere Lesbarkeit und zum anderen kann man dann auch mal die Variable
schnell auf FALSE abfragen.
Danke erstmal euch,
Kaj schrieb:> Um int zu benutzten musst du ja auch nichts extra einbinden.
Das sind aber Äpfel und Birnen. "int" ist ein eingebauter Typ (oder wie
das laut Standard benamst wird). "bool" ist eher mit "uint8_t" zu
vergleichen.
Der Typ ist zwar im (C99) Standard definiert, ist aber nicht Teil der
Sprache sondern wird über einen (Standard) Header bekanntgemacht.
Und für "uint8_t" braucht man ja auch stdint.h.
> Und ja, das gibt es beim AVR-GCC.
In meiner Installation (4.7.2 unter Linux Mint 16) ist der Header nicht
dabei.
Kompilieren tuts aber trotzdem, weil avr-gcc anscheinend den stdbool.h
des nativen gcc's benutzt.
chris schrieb:> Früher hatte man true/false so definiert:> #define false (0!=0)> #define true (0==0)
Was wiederum völlig überflüssig war. 'Logisch wahr' ist in C eindeutig
als '1' definiert und 'Logisch falsch' ist '0'. Und das nicht erst seint
C99, sondern schon ein Jahrzehnt länger.
> angenommen events_mask ist 0xfc> if (events & events_mask == true) {> ...> }
Dieser Code ist semantisch einfach falsch. Dafür kann stdbool auch
nichts. Der Code ist auch in allen anderen Programmiersprachen falsch
und wird nicht funktionieren.
> wenn du aber nach der alten Norm programmierst, funktioniert der code,> weil dann (events&events_mask) in _bool convertiert wird und dann> verglichen wird, weil true _bool ist, hingegen C99 true ist integer 1.
Nein, es wird bestenfalls nach 'int' propagiert und gegen '0'
verglichen. Das hat mit bool nichts zu tun. Zumindest nicht in C.
> Weil dies in C++ nicht passiert, weil type enforcement dort herrscht,> ist dies anfänglich nicht aufgefallen, und später war der Schaden schon> da.
Auch da kann der bool nichts für. Dein Code da oben ist auch in C++
falsch und funktioniert nicht, obwohl er syntaktisch korrekt ist und
compilierbar ist.
Ich benutze aber üblicherweise einfach einen unsigned char.
Sven P. schrieb:> unsigned char
Es gibt aber einen Unterschied zwischen einen Buchstaben und logischen
Zuständen.
Wenn im Code ein Buchstabe genutzt wird, nehme ich auch gern char,
für logische Zustände gefällt mir Boolean besser.
lutz h. schrieb:> Es gibt aber einen Unterschied zwischen einen Buchstaben und logischen> Zuständen.
Völlig korrekt. Darum nehme ich ja auch einen 'unsigned char'. Wenn ich
ein Zeichen brauche, nehm ich auch eines, nämlich 'char'.
Sven P. schrieb:> chris schrieb:>> Früher hatte man true/false so definiert:>> #define false (0!=0)>> #define true (0==0)> Was wiederum völlig überflüssig war. 'Logisch wahr' ist in C eindeutig> als '1' definiert und 'Logisch falsch' ist '0'. Und das nicht erst seint> C99, sondern schon ein Jahrzehnt länger.>
Diese (0!=0) ist, weil der resultierende Datentyp dann _Bool ist, und
bei
dem Vergleich
if (events & events_mask == true)
dann zuerst events&events_mask nach _Bool convertiert wird, was hingegen
wenn false mit 0 definiert wird nicht der Fall ist, denn dann ist der
Ausdruck Int und wird als Int ausgerechnet.
In diversen Architekturen ist _Bool z.B. das Zero oder Carryflag, hat
also nichts mit 0 oder 1 zu tun, aber wenn _Bool zu Int Convertiert
wird,
dann stimmen die Werte.
Solchen Code sieht man oft noch in public domain source code, welcher
hauptsächlich von der Unix/usenet herkam welche man doch recht oft
benutzt.
chris schrieb:> Sven P. schrieb:>> chris schrieb:>>> Früher hatte man true/false so definiert:>>> #define false (0!=0)>>> #define true (0==0)>> Was wiederum völlig überflüssig war. 'Logisch wahr' ist in C eindeutig>> als '1' definiert und 'Logisch falsch' ist '0'. Und das nicht erst seint>> C99, sondern schon ein Jahrzehnt länger.>>> Diese (0!=0) ist, weil der resultierende Datentyp dann _Bool ist,
Nein, aus Vergleichen resultiert ein 'int'.
> und> bei> dem Vergleich> if (events & events_mask == true)> dann zuerst events&events_mask nach _Bool convertiert wird,
Nein, umgekehrt. Die Konstante 'true' wird in den Datentyp von
'events&events_mask' promoted, denn der bool hat den geringsten aller
Ränge, und das wird dann irgendein 'int' werden.
> In diversen Architekturen ist _Bool z.B. das Zero oder Carryflag, hat> also nichts mit 0 oder 1 zu tun, aber wenn _Bool zu Int Convertiert> wird, dann stimmen die Werte.
Das kann die Maschine halten wie sie will, genau. Es muss dann aber
transparent umgesetzt sein.
Edit: Anm.: Das gilt für C. In C++ ergeben die Vergleiche tatsächlich
booleans. Aber auch da wird in den Typ größeren Ranges promoted, sodass
der Vergleich oben nicht funktioniert.
Sven P. schrieb:> 'Logisch wahr' ist in C eindeutig> als '1' definiert und 'Logisch falsch' ist '0'.
Da muss ich ein kleines bisschen widersprechen.
'0' ist logisch falsch und alles ungleich '0' ist logisch wahr, und
nicht nur '1'.
Kaj schrieb:> Da muss ich ein kleines bisschen widersprechen.> '0' ist logisch falsch und alles ungleich '0' ist logisch wahr, und> nicht nur '1'.
Ok, ich habs auch unvollständig formuliert.
Bei den Vergleichsoperatoren (>,<,>=,<=,==,!=) sind als Ergebnis '0'
oder '1' festgelegt für 'falsch' und 'wahr'.
Bei Bedingungen (if, ternärer Operator etc.) hast du natürlich Recht.
Schön Schön.
Und woher nehmt ihr denn nun eure bools, booleans, trues, falses, oder
was auch immer? Bzw. wie definiert ihr euch die Typen/Konstanten?
Wie gesagt, stdbool ist imho NICHT Teil einer avr-gcc Installation.
Ich schrieb bereits, dass ich schlicht 'unsigned char' und 0/1 benutze,
total unspektakulär.
Beim avr-gcc ist alternativ stdbool.h vorhanden; sie gehört allerdings
nicht zur avr-libc, sondern kommt mit dem gcc selbst.
Henry schrieb:> Und woher nehmt ihr denn nun eure bools, booleans, trues, falses, oder> was auch immer? Bzw. wie definiert ihr euch die Typen/Konstanten?
Wie, woher ich die nehme?
Wenn wir ueber C/C++ reden schreib ich
1
intmain(void)
2
{
3
boolmyVar;
4
myVar=true;
5
myVar=false;
6
7
return0;
8
}
und dann ist gut. Kein include, define oder sonst was noetig. Ehrlich
gesagt verstehe ich dein Problem nicht :/
Kaj schrieb:> Wenn wir ueber C
Das liegt aber dann entweder daran, dass du immer den C++-Compiler
benutzt oder deine Entwicklungsumgebung ungefragt schon irgendwelche
Header hereinzieht.
Bestandteil von nacktem C (C99) ist 'bool' nämlich nicht.
Kaj schrieb:> Ja, benutze tatsaechlich immer den C++-Compiler. Ist mir nie bewusst> aufgefallen^^
Dann solltest du nicht "C/C++" schreiben. Es sind halt zwei
verschiedene
Sprachen, wenn auch mit teilweise überdeckender Syntax (wobei sie
nicht überdeckend sind: beide Sprachen haben jeweils Elemente, die
die andere Sprache nicht hat).
C++ hat z.B. einen fertigen Datentyp boolean, den C nicht hat.
Wenn du C benutzt, dann würde ich einen INT Datentyp benutzten, dem du 1
oder 0 zuweist und 1 wie false und 0 wie true benutzt(oder andersrum),
denn die meisten Funktionen haben auch einen Rückgabewert(1 wen's geht
und 0 bei Fail). So wird's jedenfalls in C von A-Z beschrieben.
Dussel schrieb:> Welche hat C++ nicht?
Beispielsweise benannte Initialisierungen von Strukturen und Arrays.
Strukturen sind in C++ zwar Klassen, sodass man sowas durch
Konstrukturen ersetzen kann, aber bei Arrays gibt es dann gar keinen
entsprechenden Ersatz, und ein Headerfile, welches sowohl für C als
auch C++ gehen soll, klappt damit auch nicht.
Named address spaces wären auch noch so ein Ding, gegen das C++ sich
gewehrt hat.
12V DC schrieb:> C++ hat z.B. einen fertigen Datentyp boolean, den C nicht hat.
C hat ihn (seit C99), aber man muss dort <stdbool.h> einfügen, damit
der Compiler ihn kennt. Aber das wurde jetzt schon ein paarmal hier
geschrieben. (Intern heißt er _Bool. Mit dem header heißt er dann
bool, so wie in C++ auch.)
Hallo Jörg Wunsch,
Kannst du mich bitte aufklären, wie man standard-konform Bool bei AVR
Projekten nutzt?
Denn die avr libc bringt ja kein stdbool.h mit.
Bei mir kompilierts trotzdem, weil stdbool.h des nativen gcc benutzt
wird.
Ich hab nur Angst, dass es irgendwie ein Dummer Zufall ist.
Und mittlerweile hab ich herausgefunden dass WinAvr eine stdbool.h
mitbringt, jetzt bin ich völlig verwirrt :-)
Henry schrieb:> Danke erstmal euch,>> Kaj schrieb:>> Um int zu benutzten musst du ja auch nichts extra einbinden.> Das sind aber Äpfel und Birnen. "int" ist ein eingebauter Typ (oder wie> das laut Standard benamst wird). "bool" ist eher mit "uint8_t" zu> vergleichen.
Der Grund, warum es bool, true und false nicht ohne Header gibt, liegt
eher darin, daß es da draußen viel existierenden Code gibt, der sich
diese Namen selbst definiert. Dieser Code würde plötzlich ungültig, wenn
die auf einmal Schlüsselwörter wären. Deshalb hat man den Typ _Bool
genannt und schaltet ihn über den Header quasi frei.
> Der Typ ist zwar im (C99) Standard definiert, ist aber nicht Teil der> Sprache sondern wird über einen (Standard) Header bekanntgemacht.
Alle Standardheader sind Teil der Sprache. Das ist es ja, was sie zu
Standardheadern macht.
> In meiner Installation (4.7.2 unter Linux Mint 16) ist der Header nicht> dabei.> Kompilieren tuts aber trotzdem, weil avr-gcc anscheinend den stdbool.h> des nativen gcc's benutzt.
Das würde mich wundern, denn bei meinem 4.7.2er ist der Header dabei:
1
$ locate stdbool.h
2
/usr/include/c++/4.7/tr1/stdbool.h
3
/usr/lib/gcc/avr/4.7.2/include/stdbool.h <--- Hier ist er!
Dussel schrieb:>>beide Sprachen haben jeweils Elemente, die>>die andere Sprache nicht hat> Kurz zwischengefragt: Welche hat C++ nicht?
Das Schlüsselwort restrict.
> Alle Standardheader sind Teil der Sprache. Das ist es ja, was sie zu> Standardheadern macht.
Hihi, als ich diesen Satz schrub wusste ich schon, dass sich
irgendjemand darauf aufhängen wird.
> Das würde mich wundern, denn bei meinem 4.7.2er ist der Header dabei:$> locate stdbool.h> /usr/include/c++/4.7/tr1/stdbool.h> /usr/lib/gcc/avr/4.7.2/include/stdbool.h <--- Hier ist er!> /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdbool.h> /usr/lib/syslinux/com32/include/stdbool.h
Ja, mein Fehler, den ich dank Jörg Wunsch mittlerweile erkenn konnte.
Ich hab avr-gcc und avr libc durcheinander geschmissen und nur die
Header von Letzterem angeschaut. avr-gcc bringt stdbool.h natürlich mit.
> Kurz zwischengefragt: Welche hat C++ nicht?
Den impliziten Cast von einem void-Pointer in einen Nicht-void-Pointer.
Der Namensraum für gültige Bezeichner ist etwas kleiner (eine struct
darf nicht genauso heißen wie eine Variable, Funktion oder ein typedef;
"class", "protected", "private", "bool" etc. darf kein Bezeichner
heißen).
Das dürften die wesentlichen Stellen sein, wo sich zeigt, dass C++ keine
Obermenge von C ist.
Peter schrieb:> Ich mache den Vergleich bei if-Anweisungen immer, auch wenn sie gerade> bei Flags nicht immer benötigt werdn.
Sie werden nie benötigt, ich verstehe bis heute nicht was diese
Unsitte bringen soll außer fehlerträchtigen Code....
> Der Vorteil ist zu einem die bessere Lesbarkeit
Weil man mehr lesen und nochmal darüber nachdenken muss oder wieso? Wäre
es dann nicht noch besser sich ein "reallyTrue" und "reallyFalse" Macro
zu definieren?
> und zum anderen kann man dann auch mal die Variable> schnell auf FALSE abfragen.
Konsequenterweise müsstest du dann aber auch folgendes schreiben:
1
Booleanflag=TRUE;
2
if((flag==FALSE)==TRUE)
3
...
Ein boolean typ is sicher hilfreich, aber nicht für Vergleiche,
sondern nur um den Wertebereich einer Variablen zu definieren.
Ich halt es so:
Wenn flag als boolean deklariert ist und nur direkte Zuweißungen
stattfinden dann wird auch auf true getestet.
Stehen allerdings die einzelnen Bits für irgendwelche Zustände oder wird
irgendwelche Maskenarithmetik betrieben, dann entfällt das == true. Dann
ist flag aber auch ein uint_8 und kein bool.
Was wiederum völlig überflüssig war. 'Logisch wahr' ist in C eindeutig
als '1' definiert und 'Logisch falsch' ist '0'. Und das nicht erst seint
C99, sondern schon ein Jahrzehnt länger.
Was in jedem uC Programm schon immer gut an
while (1) {
}
zu erkennen ist, solange man nicht
for (;;){
}
nimmt.
F. Fo schrieb:> Was in jedem uC Programm schon immer gut an>> while (1) {
Man könnt ja auch while ((1 == 1) == true) hinschreiben ;-)
> }>> zu erkennen ist, solange man nicht>> for (;;){> }>> nimmt.
Das nehme ich in der Regel, weil ich es irgendwie sinniger finde, für
eine Schleife ohne Abbruch-Bedinung auch keine hinschreiben zu müssen,
statt einer pseudo-Bedingung, die halt nie false wird.
Erwin schrieb:> Und dann verschwendet Ihr für jedes Flag ein Byte ?
Wääh, schluchz! Ein ganzes Byte!
> Also ich nutze 8 einzelne Flags eines Bytes!
Bist eben ein echter Mann.
Läubi .. schrieb:> Sie werden nie benötigt, ich verstehe bis heute nicht was diese> Unsitte bringen soll außer fehlerträchtigen Code....
Kann der Rückgabewert einer Funktion auch überladen werden?
Für mich ist es nur die Frage, den Code lesbarer zu machen.
Wenn die Funktion bekannt ist, und man kennt auch den erwarteten
Rückgabewert und was dieser bedeutet, ist es nicht so wichtig. Wenn
dieses Wissen nicht da ist, ist der Vergleich eine große Hilfe, dass
Programm zu verstehen.
F. Fo schrieb:> Was wiederum völlig überflüssig war. 'Logisch wahr' ist in C eindeutig> als '1' definiert und 'Logisch falsch' ist '0'. Und das nicht erst seint> C99, sondern schon ein Jahrzehnt länger.>> Was in jedem uC Programm schon immer gut an>> while (1) {> }>> zu erkennen ist
Aha.
Und was ist mit 2? Oder 5?
Die sind auch logisch wahr. Wie jeder beliebige andere Wert auch,
der nicht 0 ist.
Also gibt es keinen Unterschied zwischen
while (1)
und
while (7)
oder
while ('p')
oder auch
while (9.5627)
lutz h. schrieb:> Kann der Rückgabewert einer Funktion auch überladen werden?> Für mich ist es nur die Frage, den Code lesbarer zu machen.
Was ist an
if (function(args) == true)
lesbarer als
if (function(args))
oder was ist an
if (function(args) == false)
lesbarer als
if (!function(args))
?
Das ist alles nur eine Gewöhnungssache.
Rufus Τ. Firefly schrieb:> Was ist an>> if (function(args) == true)>> lesbarer als>> if (function(args))
Nichts, die MISRA-Leute argumentieren das sogar noch weiter:
1
if(x==true)
ist gefährlicher als
1
if(x)
denn man könnte eines der beiden '=' vergessen und würde sich 'x'
überschreiben. Darum soll man schreiben:
1
if(true==x)
Das gibt dann einen Fehler, wenn man ein '=' vergisst, vorausgesetzt,
'true' ist keine Variable...
Zum Thema Übersichtlichkeit von ==true:
Die Lesbarkeit wird in solchen Fällen viel effektiver dadurch erhöht,
dass man Funktionen treffende Namen gibt. Boolesche Funktionen haben oft
den Präfix "is", wie bspw. in isPrime oder is_convex. Die Abfrage
1
if(isPrime(number))
2
...
liest sich dann fast schon wie Prosa, und ein zusätzliches ==true wäre
doppelt gemoppelt und würde die Sache eher unübersichtlicher machen.
Erwin schrieb:> Ein echter Mann nutzt für ein Bit doch ein uint_32 !> Mit meiner Aussage ging es mir um die Sinnhaftigkeit auf einem AVR so> vorzugehen.
Wenn man 8 zusammengehörige Flags hat, spricht meines Erachtens nichts
dagegen, die in einem Byte zusammenzufassen. Es ging hier aber um
einzelne boolesche Werte. Oder soll man sich noch 7 weitere eigentlich
unnütze Flags ausdenken, nur damit man das Byte auch komplett genutzt
hat?
lutz h. schrieb:> Läubi .. schrieb:>> Sie werden nie benötigt, ich verstehe bis heute nicht was diese>> Unsitte bringen soll außer fehlerträchtigen Code....>> Kann der Rückgabewert einer Funktion auch überladen werden?
Was meinst du mit "auch"? In C kann man Funktionen gar nicht überladen.
In C++ schon, aber da kann man keine Funktionen mit gleicher
Parameterliste und nur unterschiedlichen Rückgabetyp definieren.
Sven P. schrieb:> Nichts, die MISRA-Leute argumentieren das sogar noch weiter:
Manchmal habe ich den Eindruck, daß ein großer Teil der MISRA-Regeln nur
dazu gedacht sind, damit jemand, der keine Ahnung von C hat, auch das
Gefühl bekommt, sauberen Code geschrieben zu haben.
Yalu X. schrieb:> Zum Thema Übersichtlichkeit von ==true:>> Die Lesbarkeit wird in solchen Fällen viel effektiver dadurch erhöht,> dass man Funktionen treffende Namen gibt. Boolesche Funktionen haben oft> den Präfix "is", wie bspw. in isPrime oder is_convex.
Geschickt gewählt. Es sei angemerkt, daß isprime() z.B. nicht
ISO-Konform wäre, da alle Namen, die mit "is" anfangen, auf das
Kleinbuchstaben folgen, reserviert sind, genauso übrigens wie Namen, die
mit "str" oder mit "to" anfangen, wie z.B. "today".
@ Rolf Magnus (Gast)
>> Mit meiner Aussage ging es mir um die Sinnhaftigkeit auf einem AVR so>> vorzugehen.>Wenn man 8 zusammengehörige Flags hat, spricht meines Erachtens nichts>dagegen, die in einem Byte zusammenzufassen.
Wenn es "normale" Flags sind, ist das OK. Bei Flags zwischen normalem
Programm und Interrupts nimmt man besser ein Byte/Flag, damit hat
man atomaren Zugriff. Die Speicher"verschwendung" ist meist zu
verschmerzen. Oder so.
http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Speichern_von_globalen_Flags
"Als Alternative kann man ein nicht verwendetes Register des
I/O-Bereichs verwenden. Dabei würde sich z. B. das Register eines
zweiten UARTs, oder das EEPROM-Register anbieten, falls diese nicht
benötigt werden."
Einige AVRs haben extra dafür Register, die sonst KEINERLEI Funktionen
haben!
Rolf Magnus schrieb:> Sven P. schrieb:>> Nichts, die MISRA-Leute argumentieren das sogar noch weiter:>> Manchmal habe ich den Eindruck, daß ein großer Teil der MISRA-Regeln nur> dazu gedacht sind, damit jemand, der keine Ahnung von C hat, auch das> Gefühl bekommt, sauberen Code geschrieben zu haben.
Damit liegst du ziemlich dicht dran.
Das ist ähnlich wie mit den SPSen und AWL/ST. Damit schreibt man
effektiv unlesbare und unwartbare Programme, inklusive
Speicherzugriffsfehlern und so weiter. Aber man gibt dem Elektriker im
Feld das Gefühl, dass es viel leichter damit geht, weil eine
Programmiersprache ja viel zu kompliziert ist.
Rufus Τ. Firefly schrieb:> if (function(args) == false)>> lesbarer als>> if (!function(args))>> ?>> Das ist alles nur eine Gewöhnungssache.
Ganz einfach: Gerade das ! übersieht man leicht mal. Ich habe ja nicht
gesagt, dass der Code dadurch schneller oder robuster wird. Genau wie du
schreibst, es ist alles nur eine Sache der Gewöhnung.
Genau solche "Glaubenskriege" gibt es auch in unserer Abteilung. Ältere
Kollegen, die schon 20 Jahre dabei sind fragen nicht auf true oder false
ab. Jüngere, wie ich, machen dies schon.
Ich bin aber auch froh, dass in unserer Abteilung nur über solche
Kleinigkeiten diskutiert wird, da wir uns über den Aufbau unsere
Software vollkommen einig sind.
Ich will damit einfach sagen, dass es jeder so schreiben soll wie er es
für die Übersicht am Besten findet!
Peter schrieb:> Ich will damit einfach sagen, dass es jeder so schreiben soll wie er es> für die Übersicht am Besten findet!
Jeder schreibt seine Briefe in seinem Stil, das kann er auch bei
Software so machen, solange nicht jemand danach damit umgehen muss.
Da ich ja gerade C lerne und hier unendlich viele Beispiele von
unterschiedlichen Herangehensweisen kennen gelernt habe, frage ich mich,
wie in den Firmen überhaupt Programme zustande kommen, wenn sie nicht
einer allein macht.
Zunächst dachte ich immer, dass alles irgendwie genormt ist. Scheint es
aber nicht zu sein.
Und das verstehe ich ehrlich gesagt überhaupt nicht, denn gerade in der
Elektronik haben wir exakte Bezeichnungen und Schaltpläne, wieso dann
nicht in der Programmierung selbst.
Allein die Schreibweisen in verschiedenen Compilern ist doch schon
anders.
Für mich wird das keine Rolle mehr spielen wie ich ein Programm
schreibe, da ich das nur für mich selbst mache, aber auch da halte ich
mich an minimale Empfehlungen.
Gibt es denn eigentlich ein Standardwerk mit Empfehlungen, das man als
verbindlich ansehen kann?
F. Fo schrieb:> Zunächst dachte ich immer, dass alles irgendwie genormt ist. Scheint es> aber nicht zu sein.
Doch, ist es. C und C++ sind genormte Programmiersprachen.
> Und das verstehe ich ehrlich gesagt überhaupt nicht, denn gerade in der> Elektronik haben wir exakte Bezeichnungen und Schaltpläne, wieso dann> nicht in der Programmierung selbst.
Haben wir doch. Haben wir das?
Wie nennst du denn deine Stecker? X? oder J? Oder ST? oder CON? Und die
Transistoren? Q? T? Es gibt viele Freiheiten. Der Tiefpass ist nicht
genormt...
Natürlich gibts auch da Normen. Aber ich bezweifle, dass du z.B. die
aktuelle Norm für Schaltzeichen benutzen möchtest. In der[1] heißen
Spule, Diode und Widerstand allesamt 'R'.
> Allein die Schreibweisen in verschiedenen Compilern ist doch schon> anders.
Das wäre aber seltsam.
Allerdings bieten manche Compiler eigene Erweiterungen zur Sprache an,
die sind dann natürlich nicht mehr genormt. Der Sprachschatz z.B. bei C
ist aber sehr wohl genormt, inklusive Standardbibliothek.
Peter schrieb:> Ganz einfach: Gerade das ! übersieht man leicht mal. Ich habe ja nicht> gesagt, dass der Code dadurch schneller oder robuster wird.
Nö, aber der Code tut semantisch etwas völlig anderes.
Man kann Quelltexte übrigens auch unverständlich machen, indem man eben
solche Dingen wie '== true' anwendet. Es gibt in C eine ganze Reihe von
Idiomen, die sich im Laufe der Zeit etabliert haben und die 'jeder'
C-Programmierer versteht. Dazu gehört auch das einfache 'if(x)'. Der
erfahrenen Leser wird z.B. immer wieder über die unübliche Konstruktion
mit '== true' stolpern, das kann auch fehleranfällig sein.
[1] EN 81346-2
Sven P. schrieb:>> Allein die Schreibweisen in verschiedenen Compilern ist doch schon>> anders.> Das wäre aber seltsam.> Allerdings bieten manche Compiler eigene Erweiterungen zur Sprache an,> die sind dann natürlich nicht mehr genormt. Der Sprachschatz z.B. bei C> ist aber sehr wohl genormt, inklusive Standardbibliothek.
Ich hatte mal (ich lerne das ja gerade) versucht _BV in den Code
einzubauen, aber das Studio meckerte da und vorher lief das Programm.
Aber darauf wollte ich nicht hinaus. Es geht mir mehr um die
Schreibweisen für solche Problemstellungen.
Kann man sich denn nicht grundsätzlich auf solche Schreibweisen wie
==true oder =1 oder was auch immer einigen?
Sicher, auch in der Schaltungstechnik gibt es Unterschiede, wenigstens
ist (gerade bei neuer Norm) noch am Symbol zu erkennen, ob es ein
Widerstand oder eine Spule ist.
Allein in unserer Firma gibt es zwei verschiedene Ausführungen von
Schaltplänen. Die einen mutieren schon zu ganzen Tapeten und andere gibt
es seitenweise.
F. Fo schrieb:> Ich hatte mal (ich lerne das ja gerade) versucht _BV in den Code> einzubauen, aber das Studio meckerte da und vorher lief das Programm.
Ein wesentlicher Schritt dabei, mit einem C- (oder auch C++-) Compiler
umgehen zu lernen, ist der, Fehlermeldungen zu verstehen.
Wenn "das Studio meckert", wird also irgendwas nicht richtig sein --
hier z.B. wird vermutlich das Macro _BV nicht definiert gewesen sein.
> Kann man sich denn nicht grundsätzlich auf solche Schreibweisen wie> ==true oder =1 oder was auch immer einigen?
Natürlich kann man sich darauf einigen -- die Leute mit Erfahrung
einigen sich darauf, weder die eine noch die andere Variante zu
verwenden.
Rufus Τ. Firefly schrieb:> Ein wesentlicher Schritt dabei, mit einem C- (oder auch C++-) Compiler> umgehen zu lernen, ist der, Fehlermeldungen zu verstehen.
Das sehe ich auch so, aber wo finde ich mal ne Erklärung zu diesen meist
kryptisch wirkenden Fehlermeldungen?
F. Fo schrieb:> Ich hatte mal (ich lerne das ja gerade) versucht _BV in den Code> einzubauen, aber das Studio meckerte da und vorher lief das Programm.
Ja, aber _BV gehört auch nicht zum standardisierten C.
Du würdest genauso scheitern, wenn du CreateProcess()
gtk_recent_chooser_widget_new_for_manager() verwenden wolltest. Die
gehören nämlich auch nicht zu Standard-C sondern zum Windows-API und zu
GTK.
> Aber darauf wollte ich nicht hinaus. Es geht mir mehr um die> Schreibweisen für solche Problemstellungen.
Es gibt mehr als eine Lösung für ein Problem. Das ist in der Elektrik
aber auch nicht anders.
> Kann man sich denn nicht grundsätzlich auf solche Schreibweisen wie> ==true oder =1 oder was auch immer einigen?
Hat man doch schon vor 30 Jahren. Man lässt es weg, das ist die übliche
Konvention.
F. Fo schrieb:> Das sehe ich auch so, aber wo finde ich mal ne Erklärung zu diesen meist> kryptisch wirkenden Fehlermeldungen?
Google? Hier im Forum nachfragen? Compiler-Handbuch?
Sven P. schrieb:> F. Fo schrieb:>> Das sehe ich auch so, aber wo finde ich mal ne Erklärung zu diesen meist>> kryptisch wirkenden Fehlermeldungen?> Google? Hier im Forum nachfragen? Compiler-Handbuch?
Gute Idee, mach ich mal gleich. :-)
Manchmal kommt man ja erst durch solche Beiträge auf etwas, was einen
schon lange stört. Aber da es so viel zu lesen gibt, und ab Januar habe
ich einen Haufen ganz neues Zeug zu lernen, und die Zeit begrenzt ist,
merkt man das oft erst nach einem Hinweis - ich jedenfalls.:-)
Aber ein Link wäre trotzdem nett gewesen.
F. Fo schrieb:> Das sehe ich auch so, aber wo finde ich mal ne Erklärung zu diesen meist> kryptisch wirkenden Fehlermeldungen?
In der Dokumentation Deines Compilers.
Immer bedenken: Bei Fehlermeldungen, die ein C- oder C++-Compiler
ausgibt, ist immer die erste die interessante. Alle weiteren Meldungen
können Folgefehler sein.
Auch Warnungen sollte man ernstnehmen; gut geschriebener Code erzeugt
auch keine Warnungen.
Rufus Τ. Firefly schrieb:>> In der Dokumentation Deines Compilers.>> Immer bedenken: Bei Fehlermeldungen, die ein C- oder C++-Compiler> ausgibt, ist immer die erste die interessante. Alle weiteren Meldungen> können Folgefehler sein.>> Auch Warnungen sollte man ernstnehmen; gut geschriebener Code erzeugt> auch keine Warnungen.
Vielen Dank für den Hinweis!
Den letzten Satz sehe ich genauso und auch Warnungen sind für mich, in
meinem Code nicht akzeptabel.
Ich hoffe das auch noch in einigen Jahren sagen zu können. :-)
F. Fo schrieb:> Ich hoffe das auch noch in einigen Jahren sagen zu können. :-)
Wart mal ab, bis du die Compileroptionen -Wall und -Wextra entdeckst...
:-)
Sven P. schrieb:> F. Fo schrieb:>> Ich hoffe das auch noch in einigen Jahren sagen zu können. :-)>> Wart mal ab, bis du die Compileroptionen -Wall und -Wextra entdeckst...> :-)
Und dann muss man sich mit Warnungen abfinden oder was ist jetzt die
Aussage?
Ich hoffe ja nicht, dass du uns das damit sagen willst.
Henry schrieb:>> Und ja, das [stdbool.h] gibt es beim AVR-GCC.> In meiner Installation (4.7.2 unter Linux Mint 16) ist der Header nicht> dabei.
Dann ist deine Installation kaputt oder jemand hat sie erstellt, deer
keine Ahnung hat. stdbool.h befindet sich in
$INSTALL/lib/gcc/avr/$VERSION/include
wobei $VERSION durch die GCC-Version zu ersetzen ist, etwa 4.3.3 für
WinAVR-20100110.
In allen mir vorliegenden avr-gcc Versionen ist die stdbool.h dabei, und
die Versionen reichen von 3.4.6 bis 4.8.1.
Anmerkung: Manche Distributionen setzen gerne einen Wust von
configure-Optionen. Wenn dann stdnool.h in einen Pfad installiert wird,
der nicht in des Suchpfaden enthalten ist, findet er die stdbool.h
natürlich nicht.
Eine saubere Installation funktioniert, ohne Standard-Pfade per -L
oder -l anzugeben!