Wie benennt ihr eure Variablen eindeutig in der Programmiersprache C damit eindeutig ist welcher Typ verwendet worden ist? Gibt es da eine bewährte Methode oder erfindet da jeder Programmierer das Rad neu?
Gast
#5679864
Joern DK7JB .. schrieb: > Wie benennt ihr eure Variablen eindeutig in der Programmiersprache C > damit eindeutig ist welcher Typ verwendet worden ist? Gibt es da eine > bewährte Methode oder erfindet da jeder Programmierer das Rad neu? Nur Anfänger kommen überhaupt auf die Idee, sich um solchen völlig unwichtigen Scheiss irgendwelche Gedanken zu machen. Damit du es begreifst: es spielt absolut kein Rolle, welchen Namen ein Symbol trägt. Wichtig ist allein, dass sinnvoll dokumentiert ist, was es repräsentiert. Na klar: wenn man kann, wählt man Namen, die die wenigstens die halbe Dokumentation darstellen. Der Datentyp muss dabei allerdings nicht unbedingt erwähnt werden. Richtige Programiersprachen meckern nämlich sowieso, wenn man sich da vergreift...
Der Typ ist eindeutig, egal, wie die Variable heißt. Manche Leute benutzen eine Konvention, daß sie im Variablennamen den Typ codieren, am verbreitetsten ist die "ungarische" Notation mit vorangestellten Kürzeln wie z.B. einem kleinen "p" zur Kennzeichnung eines Pointers, ein "i" für Kennzeichnung eines Ints etc. "Ungarisch" heißt diese Konvention, weil sie von Charles Simonyi entwickelt wurde (der aus Ungarn kommt und eine Zeitlang bei Microsoft gearbeitet hat). https://en.wikipedia.org/wiki/Charles_Simonyi https://en.wikipedia.org/wiki/Hungarian_notation Eine weitere Konvention aus ähnlichem Dunstkreis ist "CamelCase", bei dem Variablennamen, die aus mehreren Wörtern zusammengesetzt werden, mit Großbuchstaben im Wort geschrieben werden - der Gegenentwurf ist die Verwendung von Unterstrichen: MeineVariableIstSchoen meine_variable_ist_schoen Ersteres mit der ungarischen Konvention gepaart kann dann so aussehen:
1 | |
2 | |
3 | |
4 | |
Wie gesagt, das liegt im Auge des Betrachters. Wirklich wichtig ist es aber, die einmal gefundene Konvention konsequent beizubehalten oder wieder abzuschaffen, aber niemals mehrere Konventionen, gar konträre, miteinander zu mischen.
Ja, da halte ich doch gleich mal dagegen, daß ich es sehr praktisch finde, wenn ich mich um solchen Mist nur da kümmern muß wo ich es auch wirklich brauche. $x=1234; $x="Ach nee besser doch nicht."; $x=(int)$x; wenns denn sein muß.
Gast
#5679900
Rufus Τ. F. schrieb: > pstrMeineVariableIstSchoen = "Bla"; > dwMeineVariableIstSchoen = 0xFFEEDDCC; > iMeineVariableIstSchoen = 6; > dblMeineVariableIstSchoen = 12.34E4; Schöne Beispiel :) Meine Erfahrungen: Falls Konventionen genutzt werden, sind diese meist angelehnt an die Ungarische Notation mit individuellen Erweiterungen. Weiteres Beispiel: Es wird nicht nur der Typ, sondern auch der Gültigkeitsbereich dem Namen voran gestellt: lokal: blMeineVariableIstSchoen = 6; // Byte lokal global: bgMeineVariableIstSchoen = 6; // Byte global main: bmMeineVariableIstSchoen = 6; // Byte innerhalb Main
Gast
#5679915
kenny schrieb: > lokal: blMeineVariableIstSchoen = 6; // Byte lokal > > global: bgMeineVariableIstSchoen = 6; // Byte global > > main: bmMeineVariableIstSchoen = 6; // Byte innerhalb Main Das ist ja super. Da könnte man ja sogar noch die Zeilennummern mit rein kodieren und den Dateinamen. Dann bräuchte man sich um einen sinnvollen prägnanten Namen keine Gedanken mehr machen.
Ich bin mal einem von Betriebspraktikanten in jahrelanger Arbeit "gepflegtem" Projekt begegnet, in dem es allen Ernstes die folgenden Variablennamen gab: a aa aaa aaaa aaaaa
Gast
#5679930
Joern DK7JB .. schrieb: > Wie benennt ihr eure Variablen eindeutig in der Programmiersprache > C > damit eindeutig ist welcher Typ verwendet worden ist? Gibt es da eine > bewährte Methode oder erfindet da jeder Programmierer das Rad neu? Das hängt von der im Betrieb eingeführten Konvention ab. Profis gestalten ihren Code vor allem inheitlich und dazu gehört eben auch die Variablen vernünftig zu benennen. Die ungarische Notation empfinde ich als sehr sinnvoll. Man erkennt Code von Anfängern oder Schluderern daran, dass die Variablennamen und die gesamte Gestaltung des Codes unleserlich und schwer zu verstehen ist. Hier spielen auch Kommentare und optische Strukturierung eine Rolle (ist ein anderes Thema, lässt sich aber ebenfalls unter dieses Thema subsummieren).
Gast
#5679936
Rufus Τ. F. schrieb: > Ich bin mal einem von Betriebspraktikanten in jahrelanger Arbeit > "gepflegtem" Projekt begegnet, in dem es allen Ernstes die folgenden > Variablennamen gab: > > a > aa > aaa > aaaa > aaaaa Selbst das könnte unter gewissen Umständen einen Sinn ergeben. Allerdings: Es ist doch sehr stark anzunehmen: Es ergibt keinen.
In Projekten an denen ich arbeite ist die einzig übliche Notation typischerweise das m_-Präfix vor Membervariablen, um die Namenskollision mit einem Getter zu vermeiden. Andere Präfixe werden nicht benutzt, und ich halte sie auch nicht für hilfreich.
Gast
#5679949
c-hater schrieb: > Nur Anfänger kommen überhaupt auf die Idee, sich um solchen völlig > unwichtigen Scheiss irgendwelche Gedanken zu machen. Damit du es > begreifst: es spielt absolut kein Rolle, welchen Namen ein Symbol trägt. > Wichtig ist allein, dass sinnvoll dokumentiert ist, was es > repräsentiert. Es spielt also "absolut kein Rolle", welchen Namen ein Symbol trägt. Na denn, wenn du das meinst. Bisher war ich der Meinung, dass nur Pfuscher eine solche Meinung haben können. Ich deklariere nur die Grundtypen per Prefix f für Flag (Bool, Ja/Nein, 1/0) i für Ganzzahl (int, long int) j für Fließkoma c für char (im Sinne eines einzelnen Zeichens) s für String p für Pointer Andere halten sich strikt an die ungarische Konvention. In Projekten muss man sich an die Projektvorgaben halten. Das sind aber auch nicht immer dieselben.
Gast
#5679959
Um Bösartigkeiten in Projekten (ausbleibende Zahlung) präventiv zu "beantworten", lassen sich Namen auf das funktionell Notwendige reduzieren. O0O0OO00 (Mischung aus 'O's und Nullen), IlIl1lII1, a010100001000001, a010100000100001, a001100000100001. Viele Spaß wünscht man dem Nachfolger, der das Projekt pflegen muss. Es ist mir aber noch nie passiert, dass ich sowas tun musste. Allerdings sind die Zeiten härter geworden, und extrem assozial. Gell C-Hater, du weißt das auch ;)
Moin, Hier gibts neben guten Tipps zu Variablennamen noch mehr: https://github.com/Droogans/unmaintainable-code Gruss WK
Gast
#5680013
Rufus Τ. F. schrieb: > Ich bin mal einem von Betriebspraktikanten in jahrelanger Arbeit > "gepflegtem" Projekt begegnet, in dem es allen Ernstes die folgenden > Variablennamen gab: > > a > aa > aaa > aaaa > aaaaa Ein Kollege nannte seine Funktionen gerne step1(), step2(), step3() und so weiter. Als er dann mal eine Funktion einfügen sollte, nannte er sie step2b(). Er war davon überzeugt, dass das viel besser sei, als normale sprechende Namen, weil man so ihre Aufruf-Reihenfolge ablesen kann. Wegen seiner Weigerung, das zu unterlassen, wurde er zum ex-Kollegen.
> wurde er zum ex-Kollegen
LOL! Das war dann wohl stepX().
El Helicoide schrieb: > c-hater schrieb: >> Nur Anfänger kommen überhaupt auf die Idee, sich um solchen völlig >> unwichtigen Scheiss irgendwelche Gedanken zu machen. Damit du es >> begreifst: es spielt absolut kein Rolle, welchen Namen ein Symbol >> trägt. > > Es spielt also "absolut kein Rolle", welchen Namen ein Symbol trägt. Tja. Ich hätte nie gedacht, daß ich das mal sage, aber wo er Recht hat, hat er Recht. Namen von Symbolen sollten vor allem aussagekräftig für den Menschen sein, der den Code lesen und pflegen muß. Der Typ ist dafür in 99.9% der Fälle aber vollkommen irrelevant bzw. wenn erforderlich, von der IDE mit nur einem Tastendruck abrufbar ("zeige die Definition des Symbols unter der Maus"). Darüber hinaus halte ich es für höchst problematisch, wenn es Variablen mit gleichem "Grundnamen", aber verschiedenem Typ gibt. Also bspw.
1 | |
2 | |
3 | |
4 | |
wie weiter oben im Thread gesehen. Es gibt also genau gar keinen Grund, den Typ irgendwie in den Variablennamen aufzunehmen. Deswegen habe ich mich ungarischer Notation und ähnlichem Unsinn auch immer strikt verweigert. Probleme hatte ich damit übrigens noch nie, denn ich habe auch noch keinen ernstzunehmenden Programmierer getroffen, der auf ungarischer Notation bestanden hätte. > Bisher war ich der Meinung, dass nur Pfuscher > eine solche Meinung haben können. Mit derartigen Ausfälligkeiten diskreditierst du dich nur selber.
Das Thema wurde hier im Forum schon sehr oft diskutiert. Hier sind zwei Beispiele für recht lange Threads mit entsprechend vielen verschiedenen Meinungen: Beitrag "Notation (Ungarische Notation)" Beitrag "Typpräfixe im Programmcode" Meine Meinung: Die Kodierung des Typs in Variablennamen - ist unnötig (beim Durchlesen von Programmcode interessiert der Variablentyp nur selten und wenn doch, ist er schnell anderweitig auffindbar), - bringt einige Nachteile mit sich (flüssiges Lesen wird erschwert, nach einer Änderung des Typs müssen alle Vorkommen der Variable geändert werden) und - eine konsequente Umsetzung ist ohnehin nicht praktikabel (bei selbstdefinierten Typen reicht ein Präfix aus 1 oder 2 Zeichen zur Typidentifikation nicht aus, und bei Funktionsnamen, wo zum Gesamttyp sowohl der Rückgabetyp als auch die Typen sämtlicher Argumente gehören, hört der Spaß endgültig auf). Ganz abgesehen davon entspricht die Microsoftsche Ungarische Notation nicht den ursprünglichen Ideen ihres Erfinders Simonyi. Zudem hat auch Microsoft längst den Unsinn darin erkannt und verbietet mittlerweile (in .NET-Bibliotheken) sogar ihre Nutzung.
Rufus Τ. F. schrieb: > Ich bin mal einem von Betriebspraktikanten in jahrelanger Arbeit > "gepflegtem" Projekt begegnet, in dem es allen Ernstes die folgenden > Variablennamen gab: > > a > aa > aaa > aaaa > aaaaa Vieleicht war das ein skalierbares Programm zum Batterie testen ;-)
Stefanus F. schrieb: > Ein Kollege nannte seine Funktionen gerne step1(), step2(), step3() und > so weiter. Als er dann mal eine Funktion einfügen sollte, nannte er sie > step2b(). Er war davon überzeugt, dass das viel besser sei, als normale > sprechende Namen, weil man so ihre Aufruf-Reihenfolge ablesen kann. Ich finde diese Idee in manchen Kontexten (z.B. Handler in State Machines) gar nicht sooo verkehrt - aber unter der Voraussetzung dass der Indizierungspräfix den Kontext identifiziert und dass die einzelnen Steps auch noch einen semantischen Namensteil haben. Fiktives Beispiel
1 | |
2 | |
3 | |
Ohne die Indizierung der Funktionen wäre sonst aus dem Code nur schwer ersichtlich in welcher Reihenfolge sie geplant waren. Ansonsten halte ich nur in Ausnahmefällen es für sinnvoll übers Knie gebrochen den Typen in den Variablennamen hinen zu kodieren. Jede moderne IDE zeigt den einem genau so gut per Tooltip o.ä. an. Ungarische Notation bringt keinen Nutzwert, erwschwert nur das Lesen. Ausnahme wären wenn beispielsweise bei Konvertierungen inhaltlich gleiche Daten in unterschiedlichen Formaten vorliegen:
1 | |
2 | |
3 | |
Moin, Wie waers denn mit: Programmiersprache wechseln? Es gibt Programmiersprachen, wo man sich ueber Variablennamen keine Gedanken machen muss - da heissen die einfach: r0..r31 oder a,x,y oder a,f,b,c,d,e,h,l... ;-D Gruss WK
Gast
#5680528
Yalu X. schrieb: > Meine Meinung: Die Kodierung des Typs in Variablennamen > - ist unnötig (beim Durchlesen von Programmcode interessiert der > Variablentyp nur selten und wenn doch, ist er schnell anderweitig > auffindbar), In Pascal stellt man bei Typ- und Klassenbezeichnern gerne ein "T" vorne ran, um zu kennzeichnen, dass es keine Variable ist. Bei C++ verwendet man da ja gern Groß- und Kleinschreibung, da gefällt mir die Präfixvariante deutlich besser. In den seltenen Fällen wo ich Pointer verwende stelle ich ein "p" vorne an, quasi als Warnblinkanlage, dass ich bei dieser Variablen besonders aufpassen muss.
Bei C-Programmen ist das eigentlich eine unsinnige Sache (wird ja auch im entsprechenden Wikipedia-Artikel zur Ungarischen Notation mit einigen Zitaten ziemlich zerrissen). Ich programmiere jedoch viel in Assembler für MSP430 und da hilft mir folgende Konvention für Präfixe: signed uns. Bedeutung ------------------------------------------------------ 8 bit b c "Byte" bzw. "Character" 16 bit s w "Short" bzw. "Word" 32 bit i q "Integer" bzw. "Quad Byte" 64 bit l o "Long long" bzw. "Octo Byte" "q" für "Quad Word" statt "dw", damit ich das Präfix auf 1 Zeichen limitieren kann, dasselbe bei 64 bit. Ist es ein Array, dann wird "a" davorgesetzt, bei Zeigern "p"; ergibt dann z.B. "ac" für einen String oder "pas" als Zeiger auf ein Array von signed 16-bit-Werten. Weiters sind die Funktionen in entsprechenden Modulen untergebracht, die typischerweise mit 3 bis max. 5 Zeichen abgekürzt werden, gefolgt von einem Unterstrich und dem eigentlichen Variablennamen, also z.B. "wPwr_BatVlt" oder "wPwr_UsbVlt" (unsigned 16 bit-Wert im Power-Modul, enthält Batterie/USB-Spannungswert) oder "sPwr_SysTmp" (signed 16 bit Systemtemperatur).
Gast
#5680568
Dergute W. schrieb: > Es gibt Programmiersprachen, wo man sich ueber Variablennamen keine > Gedanken machen muss - da heissen die einfach: r0..r31 oder a,x,y oder > a,f,b,c,d,e,h,l... ;-D Assembler ist keine Programmiersprache.
Gast
#5680571
Jürgen schrieb: > Assembler ist keine Programmiersprache. Oha, ich weiß jetzt schon, wer sich gleich dazu melden wird.
Gast
#5680597
Ich musste auch schon an Code arbeiten, der einen solchen Coding Style hatte: Präfixe ------- g: global a: array st: struct Da gab es dann ein globales array aus structs, das dann "gastReceivedMessages" hieß. Meine Meinung: Absoluter Murks. Nie den typen in den Namen schreiben. Wenn du nicht weißt, was eine Variable ist, solltest du dir überlegen, ob du da überhaupt rumcoden solltest. Die Lesbarkeit von Code hat absoluten Vorrang. Code wird mal grob geschätzt zu über 80% gelesen und zu 20% geschrieben. Und eine solchen Variablenbenamung ist nicht leserlich. Auch der übermäßige Gebrauch von typedefs ist eine Katastrophe. Die einzigen Dinge, die sinnvoll sind, sind uintX_t und solche Sachen. Das ist wenigstens halbwegs transparent. Aber eine struct würde ich nur typedef-en, wenn alle Zugriffe darauf komplett über Funktionen abstrahiert sind. So wie zum Beispiel der FILE Typ aus stdio.h. Darauf wird nur mit fopen() etc. zugegriffen. Aus diesem Grund ist IMHO C++ schon inhärent kaputt, weil die Deklaration einer struct von Haus auch ein typedef auf denselben Namen verursacht.
Gast
#5680608
M. H. schrieb: > Auch der übermäßige Gebrauch von typedefs ist eine Katastrophe. Erlaubt aber später, den darunterliegenden Typ abzuändern. Klassisches Beispiel ist "time_t" - das kann man auf 64bit abändern um Zeiten nach 2038 abbilden zu können. Gleiches gilt für mode_t, off_t usw. Das hilft auch bei der Selbst-Dokumentation des Codes: Eine Funktion "writefile (int, unsigned int, unsigned int)" ist nicht so durchsichtig. Mit Parametertypen "FILE*, mode_t, off_t" kann man schon erraten worum es geht. C++ Metaprogrammierung wäre ohne typedef gar nicht erst möglich. Da wird das intensiv genutzt.
Gast
#5680616
M. H. schrieb: > Aus diesem Grund ist IMHO C++ schon inhärent kaputt, weil die > Deklaration einer struct von Haus auch ein typedef auf denselben Namen > verursacht. Es wird kein typedef (Alias) definiert. C++ hat überhaupt keine structs, "struct" definiert Klassen, und die kann man direkt nutzen, ohne "struct" oder "class" davor. Es ist übrigens Absicht, dass man einem Typ nicht direkt ansieht, ob er jetzt ein Klasse, enum oder Alias ist - das ist ein Abstraktionsmechanismus. Alle Typen werden so einheitlich wie möglich behandelt.
Gast
#5680623
Dr. Sommer schrieb: > Es wird kein typedef (Alias) definiert. C++ hat überhaupt keine structs Na klar hat C++ structs: http://www.cplusplus.com/doc/tutorial/structures/ Und in dem Beispiel dort sieht man auch gleich das von mir angesprochene Typedef verhalten. Hat man eine Struktur namens "foo", kann man sie entweder mit struct foo bar; instantiieren oder mit foo bar;.
Gast
#5680644
M. H. schrieb: > Na klar hat C++ structs: > http://www.cplusplus.com/doc/tutorial/structures/ cplusplus.com ist keine Referenz. Da steht viel Unsinn. C++ hat keine Structs, nur Klassen. Das Schlüsselwort "struct" definiert eine Klasse, in der per default alles "public" ist. Siehe z.B.: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf S. 238: > Members of a class defined with the keyword class are private by default. > Members of a class (!) defined with the keywords struct (!) or union > are public by default. Und S. 211: class-key: class struct union https://stackoverflow.com/a/34108140 > In fact, C++ has not had structs since 1985. It only has classes. Und wie gesagt wird kein Alias definiert. Eine Klasse ist direkt ohne "struct" oder "class" davor zugänglich. Es wird einfach nicht gebraucht.
1 | |
ist in C++ das gleiche wie
1 | |
2 | |
3 | |
4 | |
Und Klassen sind nun einmal direkt zugänglich, wie eben hier per "A"; "class A" ist redundant (und hässlich). Code, welcher einen Typ nutzt, soll unabhängig davon sein, ob das jetzt eine Klasse, enum oder built-in Typ ist. Wenn ich immer "enum Mode m" schreibe, kann ich aus "Mode" keine Klasse mehr machen, wenn das nötig werden sollte. Wenn ich nur "Mode m" schreibe, geht das.
Dr. Sommer schrieb: > C++ hat /keine/ > Structs, nur Klassen. Das Schlüsselwort "struct" definiert eine > Klasse, in der per default alles "public" ist. Genau das ist der Unterschied zwischen struct und class: die Sichtbarkeit der Member, wenn sie nicht explizit angegeben wird. Und weil es einen Unterschied gibt, gibt es eben sehr wohl beides in C++. struct und class sind nicht eben nicht ganz synonym.
Gast
#5680698
Thomas M. schrieb: > Und > weil es einen Unterschied gibt, gibt es eben sehr wohl beides in C++. Wenn aber "struct" eine Klasse definiert (siehe das Zitat), wie definiert man dann structs?
Gast
#5680714
c-hater schrieb: > Damit du es > begreifst: es spielt absolut kein Rolle, welchen Namen ein Symbol trägt. > Wichtig ist allein, dass sinnvoll dokumentiert ist, was es > repräsentiert. Das erklärt vielleicht Deine mir unbegreifliche Abneigung von C gegenüber Assembler. Und es ist einfach falsch. Eine sinnvolle, intuitive bzw. den Projekt/Firmen-Gepflogenheiten entsprechende Benamung ist weit hilfreicher als eine Dokumentation. Neben den zu vernachlässigenden Schlüsselworten in C (und nur um C geht's in diesem Thread), erschaffen die gewählten Namen eines Projekts (oder einer Codebasis) ein sprachliches Universum, dessen Verständlichkeit / Nutzbarkeit mit den Benennungen steht und fällt. Jeder Mensch ist sehr erfahren in natürlicher Sprache. Und genauso wie Wortneuschöpfungen dort gewissen intuitiven Regeln unterliegen, sollten sich diese auch in Projekten/Firmen entwickeln. Wenn es ein Verb "kongen" gibt, dann gibt es naheliegende Assoziationen mit "Konger", "gekongelt" oder "KongTreff". Weil man Konventionen folgt. Und je besser man das tut, umso lesbarer wird Prosa. Das gleich gilt für Quelltexte. Was der Mensch allerdings weniger kann, ist Muster in Buchstaben oder Ziffern-Kombinationen zu "lesen". Präfixe a la pcav für pointer auf char Array volatile oder so sind oft ärgerlich. Genauso wie Lange "Selbsterklärende" Namen. Wenn jemand Annegret Kramp Karrenbauer heißt, ist AKK das kleinere Übel. Und auch ein DonauDampschiffahrtsFregattenVizeKapitän wird, wenn man das öfter auftaucht eine glücklichere Bezeichnung finden.
Thomas M. schrieb: > Dr. Sommer schrieb: >> C++ hat /keine/ >> Structs, nur Klassen. Das Schlüsselwort "struct" definiert eine >> Klasse, in der per default alles "public" ist. > > Genau das ist der Unterschied zwischen struct und class: die > Sichtbarkeit der Member, wenn sie nicht explizit angegeben wird. > Und weil es einen Unterschied gibt, gibt es eben sehr wohl beides in C++. Es gibt beide Schlüsselwörter, aber das dahinterstehende Konstrukt ist das selbe. Ich kann von einer Klasse ableiten, ihr Memberfunktionen (auch virtuelle) geben, Elemente private machen u.s.w., und das ist völlig unabhängig davon, ob ich es mit dem Schlüsselwort "class" oder dem Schlüsselwort "struct" definiert habe. Mit "struct" definiert man in C++ also nicht das, was in C eine struct wäre, sondern eine Klasse, mit allen Features, die es für Klassen in C++ gibt.
Rolf M. schrieb: > Es gibt beide Schlüsselwörter, aber das dahinterstehende Konstrukt ist > das selbe. Ja, das geht sogar soweit:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
Die Schlüsselworte "struct" und "class" sind hier überflüssig, der Typ heißt einfach nur "my_struct". Direkt austauschbar sind struct und class nicht; der Unterschied ist die standardmäßige Zuordnung zu public bzw. private.
Gast
#5680745
Nachdem ich mich schweren Herzens von meinem VB6 (Visual Basic) verabschiedet habe, habe ich mich für Python unter Ubuntu entschieden. Trotz rudimentärer Kenntnisse in C, denn in Py definierst du eine Variable und der wird ein "passender" Typ zugeordnet. Wenn man die Variable explizit typisiert, dann steht es ja da und muß nicht noch im Namen erscheinen. Das scheint mir in C doch ähnlich und deshalb macht sich der TO wohl unnötige Sorgen...und wenn ich den Typ wissen will, dann schau ich in der IDE im Quellcode nach und weiß ihn sofort. Wenn ich ein fremdes Skript verstehen will, dann ist mir der Typ der Variable doch erst mal egal. Erst wenn ich bei der Ausführung auf Probleme stosse, dann wird mich vielleicht auch der Typ interessieren. Und dann gibt der Compiler in der Regel die entsprechenden Hinweise! Z.B. "Funktion in Zeile xyz erwartet ein Array" oder "erwartet 3 Argumente, hat 2". Das alles kann man durch eine entsprechende Benennung doch nicht verhindern. Deshalb wähle ich meine Bezeichnungen immer nach der Funktion. Also test_dat_in oder norm-matrix.... Gruß Rainer
Gast
#5680752
Ich bin erstaunt, dass so viele Leute die Präfixe mögen. Aber egal, Hauptsache man macht es innerhalb eines Projektes konsistent.
Rufus Τ. F. schrieb: > Direkt austauschbar sind struct und class nicht; der Unterschied ist die > standardmäßige Zuordnung zu public bzw. private. Und dass man "class" bei Templates für Typ-Parameter verwenden kann, struct nicht. a_zip schrieb: > Trotz rudimentärer Kenntnisse in C, denn in Py definierst du eine > Variable und der wird ein "passender" Typ zugeordnet. In Python definiert man Variablen nicht. Man weist einfach was zu, und wenn sie noch nicht existiert, wird sie dann erzeugt. Und sie bekommt dann einfach den Typ, den die rechte Seite der Zuweisung hatte. Und bei der nächsten Zuweisung wieder. Nachteil ist, dass die Variable munter ihren Typ wechseln kann, ohne dass das an der Stelle auffält. Ein Fehler bei falschem Typ kommt dann erst später irgendwo tief in einem Funktionsaufruf. Und bei einem Tippfehler beim Variablennamen hat man schnell mal stillschweigend eine neue Variable angelegt, statt die schon existierende zu überschreiben. Das kann einen bei der Fehlersuche auch in den Wahnsinn treiben.
Präfixe für Typen finde ich meist überflüssig. Wichtig ist mir allerdings, schon im Namen zwischen lokalen und globalen Variablen zu unterscheiden. Lokale Variablen fangen bei mir mit Kleinbuchstaben an, globale mit Großbuchstaben. Dasselbe bei Funktionsnamen. Funktionen, die nur mit lokalen Variablen arbeiten, fangen klein an. Funktionen, die auf globale Variablen zugreifen, bekommen einen Namen, der mit Großbuchstaben anfängt. Ausnahme ist nur 'main', da er von außen vorgegeben ist. Die Länge der Variablen hängt davon ab, wie speziell die Aufgabe der Variablen ist, globale Variablen sind da naturgemäß länger. Ich benutze auch einfache Buchstaben als lokale Variablen, die aber immer dieselben Aufgaben und denselben Typ haben, egal in welcher Funktion. Meist sind es diejenigen, die Kernighan&Ritchie schon in ihren Beispielfunktionen verwendet haben. So ist 'i' immer die Indexvariable für einfache for-Schleifen und int. Stringanalyse wird mit 's' gemacht, ein Lesezeiger (const char *). Brauche ich mehrere Variablen dieser Art, fangen sie ebenfalls mit 's' an, also s1,s2 ... oder zB sr für Reststring. Das Schreiben von Strings geschieht entsprechend mit 't' (für target) als Schreibzeiger (char *).
Gast
#5680960
Jobst Q. schrieb: > globale mit > Großbuchstaben. Jobst Q. schrieb: > Funktionen, die auf globale > Variablen zugreifen, bekommen einen Namen, der mit Großbuchstaben > anfängt. Und indem man globale Variablen ganz vermeidet spart man sich auch diese Komplexität.
Gast
#5680983
Dr. Sommer schrieb: > Und indem man globale Variablen ganz vermeidet spart man sich auch diese > Komplexität. Popcorn
Gast
#5680998
Dr. Sommer schrieb: > Und indem man globale Variablen ganz vermeidet spart man sich auch diese > Komplexität. können Interrupt-Routinen dann überhaupt noch etwas sinnvolles tun?
Gast
#5681009
uC-Bastler schrieb: > können Interrupt-Routinen dann überhaupt noch etwas sinnvolles tun? ISRs sind eine Ausnahme... Man baut sich 1 globale Variable mit den relevanten Daten, auf die in der ISR 1x und ggf. in der main() 1x zugegriffen wird. Einen Zeiger/Referenz darauf übergibt man an alle Funktionen die es brauchen. So wird die globale Variable zentral genutzt und für diese 2 Funktionen braucht man dann auch keine spezielle Namenskonvention.
Rolf M. schrieb: > In Python definiert man Variablen nicht. Man weist einfach was zu, und > wenn sie noch nicht existiert, wird sie dann erzeugt Ja, sorry, habe ich auch so gemeint...Katzenklappe = 3... Gruß Rainer
Rolf M. schrieb: > In Python definiert man Variablen nicht. Man weist einfach was zu, und > wenn sie noch nicht existiert, wird sie dann erzeugt. Und sie bekommt > dann einfach den Typ, den die rechte Seite der Zuweisung hatte. Und bei > der nächsten Zuweisung wieder. Nachteil ist, dass die Variable munter > ihren Typ wechseln kann, ohne dass das an der Stelle auffält. Ein Fehler > bei falschem Typ kommt dann erst später irgendwo tief in einem > Funktionsaufruf. Und bei einem Tippfehler beim Variablennamen hat man > schnell mal stillschweigend eine neue Variable angelegt, statt die schon > existierende zu überschreiben. Das kann einen bei der Fehlersuche auch > in den Wahnsinn treiben. Ach naja, so einen Fehler kann man sich in C++ mit dem Shadowing auch leicht bauen ...
Sven B. schrieb: > Rolf M. schrieb: ... Ja, aber...und wenn es hier vielleicht nicht hingehört...du arbeitest fast immer mit Klassen, deren Methoden und Funktionen im Modul definiert sind. Damit ist schon eine große Eindeutigkeit gegeben. Weiß nicht, ob das in C genau so ist, aber in einer OO-orientierten Sprache sollte das relativ eindeutig u n d lesbar sein oder? Gruß Rainer
Sven B. schrieb: > Ach naja, so einen Fehler kann man sich in C++ mit dem Shadowing auch > leicht bauen ... Man muß aber die dann folgende Compiler-Warnung nicht ignorieren.
Gast
#5681239
A. S. schrieb: > Popcorn "Popcorn" bietet sich als Name für ein mehrdimensionales Feld an. Ist aber auf Grund der Kleinheit der einzelnen Elemente nur für Bits geeignet. Für längere Strukturen bietet sich "Rohr" oder "Kastenprofil" als Bezeichnung an. "Sabbel" dann als Bezeichnung für einen String mit > 100 Zeichen.
Dr. Sommer schrieb: > Und indem man globale Variablen ganz vermeidet spart man sich auch diese > Komplexität. Und schafft sich durch die Vermeidung neue Komplexitäten. Mir sind globale Variablen lieber als lange Parameterlisten, in denen dann oft immer wieder dasselbe steht. Da finde ich globale, also funktionsübergreifende Variablen für das, was man immer wieder braucht, deutlich praktischer. Je kürzer die Parameterlisten, um so weniger muss man auf die Reihenfolge achten. Manche Daten braucht man dauerhaft. Da finde ich es weder sinnvoll, die alle in main als lokale Variablen zu deklarieren, noch sie mit static auf die Funktionen zu verteilen.
Gast
#5681330
Jobst Q. schrieb: > Mir sind > globale Variablen lieber als lange Parameterlisten, in denen dann oft > immer wieder dasselbe steht. Daher kapselt man zusammen gehörende Daten in Klassen. Die meisten Funktionen kommen dann mit 1-3 Parametern aus, aus denen sich die Funktion dann die entsprechenden Daten holt. In Java funktioniert es doch auch - da gibt es überhaupt keine globalen Variablen.
Dr. Sommer schrieb: > Daher kapselt man zusammen gehörende Daten in Klassen. Aber innerhalb einer Klasse sind die meisten Variablen eben nicht lokal. Bei einer Quelldatei pro Klasse sind die Membervariablen im gesamten Quelltext verfügbar und damit global.
Gast
#5681420
Dr. Sommer schrieb: > In Java funktioniert es doch auch - da gibt es überhaupt keine globalen > Variablen. Deshalb ist Java auch der Renner bei uC. Oh, vertan: doch wohl eher bei Anwendungen ohne konkrete reale Objekte. Niemand sollte die Sichtbarkeit höher wählen als nötig. Und Daten sollten gekapselt und strukturiert sein. Soweit Zustimmung. Aber ob ich ein globales struct mit 100 Elementen habe, einen globalen Zeiger darauf oder eine globale Funktion die den Zeiger zurückgibt, ist oft gleichwertig.
Gast
#5681428
Jobst Q. schrieb: > Aber innerhalb einer Klasse sind die meisten Variablen eben nicht lokal. Richtig. Jobst Q. schrieb: > Bei einer Quelldatei pro Klasse sind die Membervariablen im gesamten > Quelltext verfügbar und damit global. Nur in den Funktionen eben dieser Klasse. Sie sind eben nicht global. Dass Member-Funktionen einer Klasse auf die Member-Variablen zugreifen ist klar - sonst wären es keine Member-Funktionen - womit sich die Konvention mit der Großschreibung dann erledigt. Eine Konvention die ggf. noch sinnvoll sein kann ist "i" für Index und "n" für Number (Anzahl). Ein Code kann dann so aussehen:
1 | |
Man muss halt nur wissen dass "i" hier nicht für Integer steht. A. S. schrieb: > Aber ob ich ein globales struct mit 100 Elementen habe, einen globalen > Zeiger darauf oder eine globale Funktion die den Zeiger zurückgibt, ist > oft gleichwertig. Deswegen macht man das eben nicht global. Bei vernünftiger objektorientierter Programmierung übergibt man jeder Funktion was sie gerade braucht, inklusive dem impliziten this-Pointer. So wird der Code übersichtlich und man spart sich undurchsichtige Verpflechtungen über globale Variablen. Das ist auch auf eingebetteten Systemen sehr gut machbar - habe ich schon oft. A. S. schrieb: > Deshalb ist Java auch der Renner bei uC. Man kann sich die guten Dinge da abschauen. Und ja, es gibt Java für uC.
Gast
#5681450
Jobst Q. schrieb: > Aber innerhalb einer Klasse sind die meisten Variablen > eben nicht lokal. Bei einer Quelldatei pro Klasse sind > die Membervariablen im gesamten Quelltext verfügbar > und damit global. Kuriose Sprachlogik. Alles, was nicht auf Deinen Garten beschränkt ist, ist global? Ich würde eher verschiedene Grade von Lokalität unterscheiden (blocklokal, funktionslokal, modullokal,...).
Dr. Sommer schrieb: > Jobst Q. schrieb: >> Bei einer Quelldatei pro Klasse sind die Membervariablen im gesamten >> Quelltext verfügbar und damit global. > > Nur in den Funktionen eben dieser Klasse. Sie sind eben nicht global. > Dass Member-Funktionen einer Klasse auf die Member-Variablen zugreifen > ist klar - sonst wären es keine Member-Funktionen - womit sich die > Konvention mit der Großschreibung dann erledigt. Es geht mir um die wesentliche Unterscheidung zwischen lokalen und nicht-lokalen Variablen. Die nicht-lokalen Variablen fangen bei mir mit Großbuchstaben an. Wenn dich daran die Bezeichnung global stört, ersetz es einfach durch nicht-lokal.
Jobst Q. schrieb: > Es geht mir um die wesentliche Unterscheidung zwischen lokalen und > nicht-lokalen Variablen. Diese Unterscheidung macht doch nur Sinn in einer Nicht-OO-Umgebung! Wenn du z.B. die Parameter eines Fensters in eine Klassendefinition packst, dann kannst du überall mit Class.Param drauf zugreifen und in der Klasse hast du möglicherweise den Typ expliziert definiert...das ist aber alles andere, als in einem "normalen" Progrämmchen Variablen als global zu definieren! Gruß Rainer
Joern DK7JB .. schrieb: > Wie benennt ihr eure Variablen eindeutig in der Programmiersprache C > damit eindeutig ist welcher Typ verwendet worden ist? Gibt es da eine > bewährte Methode oder erfindet da jeder Programmierer das Rad neu? Benutzt Ihr keine IDE? Meine Bezeichner sind unterschiedlich bunt, und wenn ich darüber "hover", bekomme ich den Typ auch angezeigt ...
Gast
#5681826
Wilhelm M. schrieb: > Benutzt Ihr keine IDE? Meine Bezeichner sind unterschiedlich bunt, und > wenn ich darüber "hover", bekomme ich den Typ auch angezeigt ... Eben, deswegen ist das Thema weniger wichtig, als der Geschmack der Tomaten, die ich gleich essen werde.
Gast
#5681871
Hauptsache es herrscht bei allen beteiligten mindestens projektweit Konsistenz. Besonders leserlich finde ich es aber nicht, wenn man die Namen mit Prä- und Suffixen zumüllt. Ich denke, da überwiegen die Nachteile eindeutig die Vorteile, zumal (fast) jede Popel-IDE den Typ anzeigen kann.
Leute, diese ganze Diskussion stammt doch aus einer Zeit, als man noch mit Zeileneditoren wie ed arbeitete.
Gast
#5681885
A. S. schrieb: > Deshalb ist Java auch der Renner bei uC. > > Oh, vertan Mag dir nicht klar sein, aber Java laeuft auf SIM-Karten und anderen Smart-Cards.
Gast
#5681901
Wilhelm M. schrieb: > Leute, diese ganze Diskussion stammt doch aus einer Zeit, als man > noch mit Zeileneditoren wie ed arbeitete. Oder Arduino IDE. Die war damals um 2020 noch sehr aktuell und weit verbreitet.
Stefanus F. schrieb: > Wilhelm M. schrieb: >> Leute, diese ganze Diskussion stammt doch aus einer Zeit, als man >> noch mit Zeileneditoren wie ed arbeitete. > > Oder Arduino IDE. Die war damals um 2020 noch sehr aktuell und weit > verbreitet. Was war nochmal Arduino?
Gast
#5681908
>>> Leute, diese ganze Diskussion stammt doch aus einer Zeit, als man >>> noch mit Zeileneditoren wie ed arbeitete. >> Oder Arduino IDE. Die war damals um 2020 noch sehr aktuell und weit >> verbreitet. Wilhelm M. schrieb: > Was war nochmal Arduino? Diese komische altmodische Entwicklungsumgebung ohne Debugger. Give me Five!
Stefanus F. schrieb: >>>> Leute, diese ganze Diskussion stammt doch aus einer Zeit, als man >>>> noch mit Zeileneditoren wie ed arbeitete. > >>> Oder Arduino IDE. Die war damals um 2020 noch sehr aktuell und weit >>> verbreitet. > > Wilhelm M. schrieb: >> Was war nochmal Arduino? > > Diese komische altmodische Entwicklungsumgebung ohne Debugger. > Give me Five! Ich bin enttäuscht: wir beweisen doch die Korrektheit ;-)
Gast
#5681922
Wilhelm M. schrieb: > Ich bin enttäuscht: wir beweisen doch die Korrektheit ;-) Ausnahmen bestätigen die Regel.
Der Typ ist nur selten für das Verständnis wichtig. Ich hab schon genug damit zu tun, kurze und die Funktion beschreibende Namen auszudenken, da muß ich nicht noch die Lesbarkeit durch unnütze Präfixe und Suffixe erschweren.
Gast
#5682092
Eine der erfolgreichsten Software Firmen ist Microsoft. Eine der Ursachen ist, sie beginnen jede Variable mit einem Typvorsatz und die Teile der Namen beginnen mit einem Großbuchstaben. Es gibt Profis und Stümper. Man sollte von den Profis lernen.
Profi schrieb: > Eine der erfolgreichsten Software Firmen ist Microsoft. Eine der > Ursachen ist, sie beginnen jede Variable mit einem Typvorsatz und die > Teile der Namen beginnen mit einem Großbuchstaben. Es gibt Profis und > Stümper. Man sollte von den Profis lernen. Wie schon in diesem Thread erwähnt wurde, hat selbst Microsoft eingesehen, dass das Unsinn war. Yalu X. schrieb: > Ganz abgesehen davon entspricht die Microsoftsche Ungarische Notation > nicht den ursprünglichen Ideen ihres Erfinders Simonyi. Zudem hat auch > Microsoft längst den Unsinn darin erkannt und verbietet mittlerweile (in > .NET-Bibliotheken) sogar ihre Nutzung.
Gast
#5682110
Profi schrieb: > Eine der erfolgreichsten Software Firmen ist Microsoft. Eine der > Ursachen ist, sie beginnen jede Variable mit einem Typvorsatz und die > Teile der Namen beginnen mit einem Großbuchstaben. Es gibt Profis und > Stümper. Man sollte von den Profis lernen. Laut Wikipedia: https://de.wikipedia.org/wiki/Ungarische_Notation sollte eigentlich der Verwendungszweck angegeben werden. Die Notierung des Datentyps ist > für den schlechten Ruf der Konvention verantwortlich, weil die Benennung einer Variablen nach dem Datentyp wenig zum Verständnis des Inhalts beiträgt und trotzdem viel Aufwand verursacht. Typo-Konventionen (z.B. CamelCase oder _) oder ein Präfix n für Anzahl, i für Index oder auch p für Pointer sind doch ok. Schlimm sind "pac" für pointer auf Array of char oder "i" bzw. "i32" für Integer.
A. S. schrieb: > Typo-Konventionen (z.B. CamelCase oder _) Ich wusste gar nicht, dass es für Schreibfehler (typo) Konventionen gibt ;-)
Egon D. schrieb: > Alles, was nicht auf Deinen Garten beschränkt ist, ist > global? > > Ich würde eher verschiedene Grade von Lokalität unterscheiden > (blocklokal, funktionslokal, modullokal,...). Dann sagt lokal garnichts mehr aus. Blocklokal ist zwar möglich, aber nicht sinnvoll. Modullokal ist eben nicht mehr lokal, man könnte modulregional sagen, wenn man das Wort global nicht mag. Solange ein Programm nur aus einem Modul bzw einem Quelltext besteht, ist global und modulregional identisch. Erweitert man nun das Programm um ein Modul, sind alle bisher globalen Variablen nicht mehr global im Sinne von programmweit gültig, obwohl sich nichts an ihnen geändert hat. Global wären dann nur noch Variablen, die als extern deklariert sind. Der Unterschied zwischen modulweit und programmweit ist also eher theoretischer Natur. Dagegen ist der Unterschied zu (funktions-)lokalen Variablen drastisch und von großer praktischer Bedeutung. Lokale Variablen sind im allgemeinen auch temporär, also zeitlich nur gültig solange sie abgearbeitet wird. Es gibt zwar auch die Möglichkeit statische Variablen in einer Funktion zu deklarieren, das schafft aber meist mehr Probleme als sie löst.
Jobst Q. schrieb: >> Ich würde eher verschiedene Grade von Lokalität unterscheiden >> (blocklokal, funktionslokal, modullokal,...). > > Dann sagt lokal garnichts mehr aus. Blocklokal ist zwar möglich, aber > nicht sinnvoll. Modullokal ist eben nicht mehr lokal, man könnte > modulregional sagen, wenn man das Wort global nicht mag. Deine Definition von "lokal" beschränkt sich auf eine Weltsicht von "es gibt Funktionen und die haben ein drinnen (lokal) und ein draußen (global)". Das ist manchmal sinnvoll und manchmal nicht. Vor allem schränkt es dich in deiner Denkweise stark ein. Wenn ich ein Buch verleihe, dann mache ich es jemandem zugänglich, der außerhalb meines Scopes liegt (ergo: nicht lokal). Aber deswegen mache ich es noch lange nicht jedem Menschen auf dieser Welt zugänglich (ergo: nicht global). Im Übrigen nutze ich blocklokale Variablen sehr gerne (z.B. in Schleifen).
Jobst Q. schrieb: > Solange ein Programm nur aus einem Modul bzw einem Quelltext besteht, > ist global und modulregional identisch. Erweitert man nun das Programm > um ein Modul, sind alle bisher globalen Variablen nicht mehr global im > Sinne von programmweit gültig, obwohl sich nichts an ihnen geändert hat. > Global wären dann nur noch Variablen, die als extern deklariert sind. Eine etwas merkwürdige Logik. Wenn man ihr weiter folgt, wären alle lokalen Variablen auch global, solange man nur eine Funktion (also main()) hat, da man sie ja dann auch vom ganzen Programm aus sieht und sie auch über die gesamte Programmlaufzeit existieren.
Gast
#5682626
Rolf M. schrieb: > solange man nur eine Funktion (also > main()) hat, da man sie ja dann auch vom ganzen Programm aus sieht und > sie auch über die gesamte Programmlaufzeit existieren. Wenn Du so willst, ja. Bzw. Nein. Auch dann würdest Du ja (nach der Initialisierung) eine Endlosschleife haben. Und die wiederum hat viele Blöcke, von denen aus gesehen es lokale (nur innerhalb dieses Blocks) und globale (oberhalb dieses Blocks) Variablen gibt. Wenn auch Spaghtetti-Code, das Prinzip ist gleich (nur, dass die Blöcke im Gegensatz zu Funktionen keine Parameter) Von daher finde ich die Unterscheidung Stimmig, egal ob Block, File oder Projekt: Globale Variablen (von außerhalb) Parameter (Übergeben) lokale Varialen (nur innerhalb)
A. S. schrieb: > Und die wiederum hat viele Blöcke, von denen aus > gesehen es lokale (nur innerhalb dieses Blocks) > und globale (oberhalb dieses Blocks) Variablen gibt. Membervariablen sind aus mehreren Blöcken (nämlich den Methoden) erreichbar, gleichzeitig aber nur von dort. Wie würdest du sie einordnen? Lokal, global oder doch keins davon?
Gast
#5682645
Profi schrieb: > sie beginnen jede Variable mit einem Typvorsatz und die > Teile der Namen beginnen mit einem Großbuchstaben. Es gibt Profis und > Stümper. Man sollte von den Profis lernen. Man kann aber auch den Linux Kernel anschauen Beispiel: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/audit.c Das ist auch ein großes Projekt und ziemlich erfolgreich. Klar. Das ist kein riesen SW-Unternehmen. Trotzdem ist es Code von hoher Qualität, obwohl der Coding-Style so ziemlich das Gegenteil ist. Das wichtigste meiner Meinung nach ist, dass es sich flüssig liest. Und das ist, finde ich, bei ungarischer Notation nicht der Fall. Auch die Einrückung des Codes um einen TAB (entspricht 8 Leerzeichen) hilft, dass der Code sehr lesbar ist, obwohl vermutlich die meisten mit dem Kopf darüber schütteln
Rolf M. schrieb: > Jobst Q. schrieb: > >> Solange ein Programm nur aus einem Modul bzw einem Quelltext besteht, >> ist global und modulregional identisch. Erweitert man nun das Programm >> um ein Modul, sind alle bisher globalen Variablen nicht mehr global im >> Sinne von programmweit gültig, obwohl sich nichts an ihnen geändert hat. >> Global wären dann nur noch Variablen, die als extern deklariert sind. > > Eine etwas merkwürdige Logik. Wenn man ihr weiter folgt, wären alle > lokalen Variablen auch global, solange man nur eine Funktion (also > main()) hat, da man sie ja dann auch vom ganzen Programm aus sieht und > sie auch über die gesamte Programmlaufzeit existieren. Das ist nicht meine Logik, deshalb "im Sinne von programmweit gültig". Von manchen wird global so verstanden, ich habe es eher als nicht-lokal verstanden und so ist auch die Unterscheidung in meiner Benennungskonvention: Nur lokale (temporäre) Variablen beginnen mit Kleinbuchstaben.
S. R. schrieb: > Membervariablen sind aus mehreren Blöcken (nämlich den Methoden) > erreichbar, gleichzeitig aber nur von dort. > > Wie würdest du sie einordnen? Lokal, global oder doch keins davon? Könnte man regional nennen.
Gast
#5682742
M. H. schrieb: > Das ist auch ein großes Projekt und ziemlich erfolgreich. Klar. Das ist > kein riesen SW-Unternehmen. Trotzdem ist es Code von hoher Qualität, Nein, er ist nur von durchgängig ziemlich gleicher, aber nicht von wirklich hoher Qualität. Um das ganz klar zu sagen: Auch dieser Zustand ist ein Zustand, der den Linux-Kernel ganz klar über die meiste kommerzielle Software erhebt. Aber leider: immer noch weit entfernt von Perfektion. Man braucht einfach mal nur die Kernel-Updates zu verfolgen, um einen Eindruck davon zu bekommen, wo die Säge klemmt. Das sind immer und immer wieder Sachen, die mit einer richtigen Hochsprache einfach garnicht erst passieren könnten. Sprich: hier ist schlicht die (wegen der Effizienz gewollte) Maschinennähe und deren gleichzeitig unzureichende Unterstützung durch die gewählte Programmiersprache "Schuld" an den Sicherheitslücken. Im Endeffekt ist es aber natürlich die Unfähigkeit der reinen Hochsprachenprogrammierer, die potentiellen Sicherheitslücken auch ohne Compilerhilfe (bzw. die Hilfe eines Laufzeitsystems) vorausschauend erkennen und verhindern zu können. > obwohl der Coding-Style so ziemlich das Gegenteil ist. Assemblernah, soweit es C halt zuläßt. Absolut sinnvoll im Sinne der Aufgabe. Das Ziel des aus der Sicht der C-only-Wichser "schlechten" Codierstils ist ganz klar: Wir machen es dem Compiler so einfach wie möglich, effizienten Code zu erzeugen. Weil wir (im Gegensatz zu diesen unsäglichen C-Only-Wichsern) wissen, dass Compiler halt nach wie vor weit weg davon sind, perfekt zu sein.
Gast
#5682745
c-hater schrieb: > C-only-Wichser Ja, gute Programmierer können auch noch mehr Sprachen wie Python, Scala, Scheme, Mathematica, SQL, Haskell, Erlang, JavaScript, Java, ... und können von dort Paradigmen übernehmen.
c-hater schrieb: > unsäglichen C-Only-Wichsern Sagt der unsägliche c-hater.
Dr. Sommer schrieb: > c-hater schrieb: >> C-only-Wichser > > Ja, gute Programmierer können auch noch mehr Sprachen wie Python, Scala, > Scheme, Mathematica, SQL, Haskell, Erlang, JavaScript, Java, ... und > können von dort Paradigmen übernehmen. Und gute Programmieren können vor allem auch Assembler, oft von all den Sache, mit denen sie im Läufe der Jahrzehnte Kontakt hatten. z80, 8048, 8051, x86, AVR, ARM jeweils privat, oder eben /370 beruflich, wenn auch schon 2 Jahrzehnte nicht mehr. Einfach nur die Mainstreamsprache zu hassen ist keine Leistung. Selbst wenn man bei C die Freiheit hat sich Probleme einzufangen, Assembler ist C darin haushoch überlegen.
Rufus Τ. F. schrieb: > Eine weitere Konvention aus ähnlichem Dunstkreis ist "CamelCase", bei > dem Variablennamen, die aus mehreren Wörtern zusammengesetzt werden, mit > Großbuchstaben im Wort geschrieben werden Am übersichtlichsten. Den Typ da noch reinzuquetschen ist vollkommen überflüssig. Axel S. schrieb: > sein, der den Code lesen und pflegen muß. Der Typ ist dafür in 99.9% der > Fälle aber vollkommen irrelevant bzw. wenn erforderlich, von der IDE > mit nur einem Tastendruck abrufbar ("zeige die Definition des Symbols > unter der Maus"). Genau. Und "Konstanten.hh" und "Variablen.hh" mit Blöcken für verschiedene Routinen, wo Variablen und Konstanten zusammengelegt werden, machen das Ganze übersichtlich genug. Rufus Τ. F. schrieb: > Ich bin mal einem von Betriebspraktikanten in jahrelanger Arbeit > "gepflegtem" Projekt begegnet, in dem es allen Ernstes die folgenden > Variablennamen gab: > > a ... > aaaaa In kurzen Routinen mache ich mir nicht die Mühe, Variablen, insbesondere die Loop- und Umrechnungsvariablen, anders als x,y,z, zu benennen.
Gast
#5683592
Marc V. schrieb: > In kurzen Routinen mache ich mir nicht die Mühe, Variablen, > insbesondere die Loop- und Umrechnungsvariablen, anders als x,y,z, > zu benennen. Also zumindest bei geschachtelten Schleifen und mehrdimensionalen Arrays verwende ich sprechende Laufvariablen da man selber oder der nächste sie zu leicht verwechselt.
Blechbieger schrieb: > Also zumindest bei geschachtelten Schleifen und mehrdimensionalen Arrays > verwende ich sprechende Laufvariablen da man selber oder der nächste sie > zu leicht verwechselt. 'laufvariable' ist vielleicht geschwätziger, sagt aber auch nicht mehr als 'i'. Und wenn es um verschachtelte Schleifen geht, sagt 'i1' 'i2' usw auch ohne Buchstabenballast etwas über die Tiefe der Verschachtelung aus.
Gast
#5683787
1 | |
2 | |
3 | |
4 | |
halte ich schon für übersichtlicher als x,y,z insbesondere wenn mit den Variablen noch gerechnet werden soll.
Carl D. schrieb: > Selbst wenn man bei C die Freiheit hat sich Probleme einzufangen, > Assembler ist C darin haushoch überlegen. Das ist signaturverdächtig. :-)
Gast
#5683796
Blechbieger schrieb: > halte ich schon für übersichtlicher als x,y,z insbesondere wenn mit den > Variablen noch gerechnet werden soll. Im 3D-Raster passt's doch.
Blechbieger schrieb: > Also zumindest bei geschachtelten Schleifen und mehrdimensionalen Arrays > verwende ich sprechende Laufvariablen da man selber oder der nächste sie > zu leicht verwechselt. Kommt darauf an. x,y,z können nur Loop- oder Umrechnungsechnungsvariablen sein. Wenn man sich angewöhnt hat, die Variablen auch in dieser Reihenfolge zu verwenden, gibt es keine Probleme, da immer Array[x][y][z]. Dabei ist für mich x immer die Breite, y die Höhe und z die Tiefe. Das hat auch noch den Vorteil, dass man nicht raten muss, ob diese Variablen noch für irgendetwas anderes benutzt werden. Natürlich benutze ich auch sinnvolle Namen - da wo es nötig ist. Ausführliche Kommentare (auch schon bei der Deklaration der Variablen/Konstanten) finde ich jedoch viel nützlicher. Man lernt so etwas spätestens dann zu schätzen, wenn nach ein paar Monaten etwas im Programm geändert werden muss. Rufus Τ. F. schrieb: > Ich bin mal einem von Betriebspraktikanten in jahrelanger Arbeit > "gepflegtem" Projekt begegnet, in dem es allen Ernstes die folgenden > Variablennamen gab: > > a Wenn wir schon von Kollegen reden - schreibfaule Typen, die Zeilen sparen wollen sind (für mich) viel schlimmer. Wir hatten mal einen, der fast immer Dutzend oder mehr Variablen, die zwar alle vom selben Typ waren, aber quer durch Programm in verschiedenen Routinen benutzt wurden, in einer Zeile deklariert hat, um Deklarationen so kurz wie möglich zu halten - prost mahlzeit.
C und C++ sind nicht stark typisiert, sodass die Verwendung von einer Notation durchaus nützlich sein kann. Vergleiche beispielsweise implizite casts unsigned and signed Typen unterschiedlicher Bitbreite in C und Go. Am besten eine funktionale Sprache ohne Variablen verwenden ... F# oder Haskell ;)
Gast
#5683997
Ach, hier tummeln sich mal wieder die selbsternannten Pseudo-Gurus und stellen ihre erweiterten Regeln für C gegenseitig vor. Klasse! Selbstverständlich reicht es nicht aus, sowas wie goto zu verteufeln, nein, man muß auch alle gängigen Typen umbenennen und alle Zahlen außer 0 und 1 aus einem anständigen Programm entfernen und durch Bezeichner ersetzen, die dann in 37 verschiedenen Fremd-Dateien verschiedener Hersteller in die betreffende Zahl umgesetzt werden - und die betreffenden Dateien gehören selbstverständlich NICHT zum Projekt. Sowas treibt natürlich die schiere Anzahl von Bezeichnern in astronomische Höhen, was offenbar gewollt ist. Merkt sich alles prima, wenn man sonst nix im Kopf hat, gelle? Mit irgend etwas muß selbiger ja gefüllt werden... Hat mir dies doch neulich jemand angeraten. Das Schöne daran ist, daß er mir versprach, sich nicht mehr mit mir unterhalten zu wollen, solange ich seiner grandiosen Regel nicht nachkäme. Juchhei, endlich hält dieser Kerl seine Klappe und nervt mich und den Rest der Welt nicht mehr mit seinen Kommentaren. Ist ein erheblicher Gewinn für's Forum. Hoffentlich hält er sich auch an sein Versprechen und ans Klappe-Halten. Aber sowas ist selbstverständlich nur der Anfang. Man muß schließlich auch Regeln für das Benennen von Typen, Variablen, Funktionen und sonstwas aufstellen, wo kämen wir denn hin, wenn irgend jemald so einfach nur den gesunden Menschenverstand walten ließe? Also, um hier nen positiven Beitrag zu leisten, schlage ich vor, auch ein Kürzel des Autors sowie ein weiteres Kürzel die Datei betreffend, wo die Entität deklariert worden ist, in den Namen dieser Entität aufzunehmen. Kurze und prägnante Namen kann ja jeder, das muß weg! So richtig lange und aussagekräftige Namen müssen her, die man nur entziffern kann, wenn man die dazu zu befolgenden Regeln sich ausdruckt und an die Wand pinnt. Sowas nennt man dann Fortschritt oder C 2019. Ich habe mich übrigens neulich nicht getraut, den Verkäufer nach ner tragbaren USB-Festplatte mit 4 Tera-Uint8Tees zu fragen. Aber vielleicht kann das ja mal einer von euch probieren und davon berichten. Also: Beckmesser war die Knalltüte in Wagners Meistersingern, der selber zwar nicht wirklich singen konnte, dafür aber mit dem Buch der ehernen Regeln unter'm Arm herum lief und allen Meistern ihre angeblichen Regelverstöße vorhalten wollte. Eben so einer aus der Klasse der selbsternannten Gurus. Aber er konnte deshalb trotzdem nicht gut singen. Eine Backpfeife eben. W.S.
Carl D. schrieb: > Und gute Programmieren können vor allem auch Assembler, oft von all > den Sache, mit denen sie im Läufe der Jahrzehnte Kontakt hatten. Nicht jeder gute Programmierer hat vor mehreren Jahrzehnten angefangen, die damaligen Systeme (mangels Alternativen) in Assembler zu programmieren. Manche sind auch schlicht nicht alt genug.
Beitrag #5684146 wurde von einem Moderator gelöscht.
Gast
#5684176
Lieber Dr. Sommer, bitte unterlasse doch solche vor allem Anfänger verwirrenden Aussagen: 1.) Dr. Sommer schrieb: > C++ hat überhaupt keine structs 2.) Dr. Sommer schrieb: > M. H. schrieb: >> Na klar hat C++ structs: >> http://www.cplusplus.com/doc/tutorial/structures/ > > cplusplus.com ist keine Referenz. Da steht viel Unsinn. C++ hat keine > Structs, nur Klassen. Das Schlüsselwort "struct" definiert eine > Klasse, in der per default alles "public" ist. Siehe z.B.: 3.) Dr. Sommer schrieb: > Wenn aber "struct" eine Klasse definiert (siehe das Zitat), wie > definiert man dann structs? Zu 1.) Wenn C++ keine structs hätte, gäbe es in C++ das Schlüsselwort "struct" nicht bzw. müsste bei Verwendung zu einer Fehlermeldung führen. zu 2.) Ob cplusplus.com nun EINE Referenz für C++ ist oder eben DEINE Referenz für C++ gerade nicht ist, spielt keine Rolle. Tatsache ist, es gibt das Schlüsselwort struct in C++, nur dessen Bedeutung ist halt anders als in C, siehe https://de.cppreference.com/w/cpp/keyword https://namespace-cpp.de/std/doku.php/kennen/keywords "Klassen und Strukturen (struct) sind in C++ gleichwertig mit einer Ausnahme: Das voreingestellte Zugriffsrecht einer Klasse ist private. C, C++ : Das Schlüsselwort struct leitet die Deklaration bzw. Definition eines Verbunddatentyps (Struktur) ein, der Daten unterschiedlicher Typen bündelt. In C++ dürfen Strukturen, anders als in C, auch Methoden enthalten. Damit sind Klassen (class) und Strukturen gleichwertig mit einer Ausnahme: Das voreingestellte Zugriffsrecht einer Struktur ist public." zu 3.) Brauchst du Beispiele dafür? http://programmingexamples.wikidot.com/struct
Anfänger schrieb: > Wenn C++ keine structs hätte, gäbe es in C++ das Schlüsselwort "struct" > nicht bzw. müsste bei Verwendung zu einer Fehlermeldung führen. Das ist doch nur eine Definitionsfrage. C++ hat keine „reinen“ structs, das Schlüsselwort "struct" ist dort nur ein alternatives Schlüsselwort für Klassen. Aber das wurde nun schon zur Genüge hier durchgekaut.
Gast
#5684299
Anfänger schrieb: > Zu 1.) Wenn C++ keine structs hätte, gäbe es in C++ das Schlüsselwort > "struct" nicht bzw. müsste bei Verwendung zu einer Fehlermeldung führen. Es gibt hier 2 Ebenen. Die Syntax und die Semantik. Das ist auch etwas, das Anfänger verstehen müssen. In der Syntax steht zwar "struct", aber die Bedeutung ist "Klasse". Anfänger schrieb: > Ob cplusplus.com nun EINE Referenz für C++ ist oder eben DEINE Referenz > für C++ gerade nicht ist, spielt keine Rolle. Die einzige Referenz die zählt ist der C++ Standard. Den habe ich zitiert. Und da gibt es keine Strukturen, nur Klassen, welche man über die Schlüsselwörter "struct" oder "class" definieren kann. Anfänger schrieb: > "Klassen und Strukturen (struct) sind in C++ gleichwertig mit einer > Ausnahme: Das voreingestellte Zugriffsrecht einer Klasse ist private. Irgendwelche Websiten - noch dazu deutsche Übersetzungen - sind irrelevant. Im Internet und sogenannten Online-Tutorials und auch in Büchern wird unendlich viel Blödsinn über C++, aber auch über C, verbreitet. Nur der Standard zählt. Das "struct" Keyword wird da sogar oft in Beispielen verwendet - um Klassen zu definieren.
Anfänger schrieb: > Ob cplusplus.com nun EINE Referenz für C++ ist oder eben DEINE Referenz > für C++ gerade nicht ist, spielt keine Rolle. Tatsache ist, es gibt das > Schlüsselwort struct in C++, nur dessen Bedeutung ist halt anders als in > C, siehe > > https://de.cppreference.com/w/cpp/keyword > https://namespace-cpp.de/std/doku.php/kennen/keywords Nunja, die einzige wirkliche Referenz für C++ ist die ISO-Spezifikation. Dort heißt es in Kapitel 9 "Classes": A structure is a class defined with the class-key struct; its members and base classes (clause 10) are public by default
Rolf M. schrieb: > > A structure is a class defined with the class-key struct; its members > and base classes (clause 10) are public by default was den Vorteil hat, kompatibel zu bestehendem C-Code zu sein. Das, die Kompatibilität zur Vorgängern/Vorversionen ist der Grund für jede C++ "Sprachungereimtheit". Das ist aber auch der Grund dafür, daß sich C++ mit so vielen "besseren" Sprachen vergleichen lassen muß. Es hat sie schlicht alle überlebt.
Carl D. schrieb: > Rolf M. schrieb: >> >> A structure is a class defined with the class-key struct; its members >> and base classes (clause 10) are public by default > > was den Vorteil hat, kompatibel zu bestehendem C-Code zu sein. Ja, das Schlüsselwort struct existiert hauptsächlich aus Gründen der Abwärtskompatibilität zu C und nicht etwa, um dem faulen Programmierer das Tippen des Wörtchens "public" zu ersparen. Es wäre ja sonst ziemlich unsinnig, für die beiden Dinge (class und struct), die sich lediglich in der defaultmäßigen Sichtbarkeit ihrer Elemente unterscheiden, so völlig unterschiedliche Bezeichnungen zu wählen. Deswegen benutze ich struct ausschließlich C-like, d.h. für reine Datenstrukturen ohne Elementfunktionen, und class ausschließlich für echte Klassen, d.h. solche, die nicht nur Datenelemente, sondern auch Elementfunktionen enthalten. Auch eine (selten vorkommende) echte Klasse, in der sämtliche Elemente public sind, ist bei mir eine class, auch wenn ich mit struct etwas weniger zu tippen hätte. Das ganze ist natürlich eine eher philosophische bzw. linguistische Frage, aber wenn man schon die freie Wahl hat, dürfen auch mal die Geisteswissenschaften zu Wort kommen ;-)
Yalu X. schrieb: > Deswegen benutze ich struct ausschließlich C-like, d.h. für reine > Datenstrukturen ohne Elementfunktionen, und class ausschließlich für > echte Klassen, d.h. solche, die nicht nur Datenelemente, sondern auch > Elementfunktionen enthalten. Auch eine (selten vorkommende) echte > Klasse, in der sämtliche Elemente public sind, ist bei mir eine class, > auch wenn ich mit struct etwas weniger zu tippen hätte. Den besten Vorschlag den ich zu dieser Unterscheidung gehört habe, war "class" für Dinge zu verwenden, die eine Invariante haben. Wenn jeder beliebige Wert für jedes der Member ok ist, ist "struct" meist sinnvoll. Das passt auch ziemlich gut zu dem, was man so intuitiv tun würde. Es passt auch gut zu dem "alles ist public"-Konzept.
W.S. schrieb: > nein, man muß auch alle gängigen Typen umbenennen und alle Zahlen außer > 0 und 1 aus einem anständigen Programm entfernen und durch Bezeichner > ersetzen, die dann in 37 verschiedenen Fremd-Dateien verschiedener > Hersteller in die betreffende Zahl umgesetzt werden - und Es ist bestens bekannt, daß Du Fan von "magic numbers" im Quelltext bist, denn die lassen sich ja viel einfacher im Datenblatt finden.
Gast
#5685199
Rufus Τ. F. schrieb: > Es ist bestens bekannt.. Ach, du nörgelst mal wieder. Aber ich kann dich trösten: Das zuständige Hardware-Register, wo die Zahl reinkommt, findet man im RefManual ganz leicht. Und dann sieht man auch im zugehörigen Text sowohl die Stelle, wo die Zahl hinkommt, als auch.. _TADAA!_ eine zumeist relativ ausführliche Beschreibung, was verschiedene Werte für diese Zahl tatsächlich bewirken. Aus dem schieren Namen geht das nämlich selten bis nie hervor. Das ist der wahre Sinn von Refrenz-Manuals - und von den dort nachlesbaren Zahlenwerten. Ansonsten seid ihr ja noch immer beim Vergleichen eurer allerbesten Einschränkungen für Variablen-Bezeichner. Aber daß ihr jetzt beim Käuen von C++ und Klassen versus Structs angekommen seid, ist ein Abdriften vom eigentlichen Thema. Reißt euch zusammen und kreiert endlich die ultimative Vorschrift zum Bilden eines qualifizierten Variablennamens. Die Welt wartet sehnsüchtig drauf! Ach ja, anbei fällt mir ein, daß man ja dann auch an die Chip-Hersteller herantreten müßte - wo unser wackerer Rufus das Thema schon angeschnitten hat. Die Bezeichner für Bitgruppen in den Hardwareregistern entsprechen ja selten bis nie den noch festzulegenden Variablennamen. Das muß natürlich sofort geändert werden - und dafür sind dann die Chiphersteller heranzuziehen. W.S.
W.S. schrieb: > Das zuständige Hardware-Register, wo die Zahl reinkommt, findet man im > RefManual ganz leicht. Ärgerlicherweise wird das Hardwareregister dort aber mit einem Namen angesprochen, statt dessen viel eindeutigere und verständlichere Adresse zu verwenden. Denn letztlich ist doch genau das Deine > ultimative Vorschrift zum Bilden eines qualifizierten Variablennamens. Das hier ist doch viel verständlicher und eingängiger :
1 | |
2 | |
als das hier:
1 | |
2 | |
oder?
Gast
#5685411
W.S. schrieb: > die dann in 37 verschiedenen Fremd-Dateien verschiedener > Hersteller in die betreffende Zahl umgesetzt werden - und die > betreffenden Dateien gehören selbstverständlich NICHT zum Projekt. > Sowas treibt natürlich die schiere Anzahl von Bezeichnern in > astronomische Höhen, was offenbar gewollt ist. Merkt sich alles prima, > wenn man sonst nix im Kopf hat, gelle? Mit irgend etwas muß selbiger ja > gefüllt werden... > Aber sowas ist selbstverständlich nur der Anfang. Man muß schließlich > auch Regeln für das Benennen von Typen, Variablen, Funktionen und > sonstwas aufstellen, wo kämen wir denn hin, wenn irgend jemald so > einfach nur den gesunden Menschenverstand walten ließe? > Also, um hier nen positiven Beitrag zu leisten, schlage ich vor, auch > ein Kürzel des Autors sowie ein weiteres Kürzel die Datei betreffend, wo > die Entität deklariert worden ist, in den Namen dieser Entität > aufzunehmen. Kurze und prägnante Namen kann ja jeder, das muß weg! So > richtig lange und aussagekräftige Namen müssen her, die man nur > entziffern kann, wenn man die dazu zu befolgenden Regeln sich ausdruckt > und an die Wand pinnt. Du sprichst mir bei dem Post in allen Punkten aus der Seele. Nur bei den NamensRegeln möchte ich unterscheiden: a) Regeln, die sich jemand ausdenkt, und an die sich dann alle halten sollen. --> Das führt bei uns regelmäßíg ins Chaos. Das ist so, als würde man ein Schrauben-Lager einrichten wollen, ohne zu wissen welche Typen/Größen und in welchen Mengen. b) Regeln, die evolutionär aus gewachsenem Code entstehen. --> Hier gibt es häufig mehrere Strömungen, bestimmte Token-Typen zu benennen. Nach einiger Zeit überwiegt eine Art und die anderen treten bei Neubenennungen in den Hintergrund. Nach weiterer Zeit werden diese als unnatürlich empfunden, aus der Hauptströumg eine Regel formuliert und die anderen refakturiert.
W.S. schrieb: > Reißt euch zusammen und kreiert endlich die ultimative Vorschrift zum > Bilden eines qualifizierten Variablennamens. Die Welt wartet sehnsüchtig > drauf! Niemand zwingt dich dazu, deine Variablen so zu benennen - bleib doch einfach bei: a, ab, abc etc. wenn dich das glücklich macht. Zusätzlich zu den sinnvollen Variablennamen setze ich bei Konstanten immer ein c_ davor, etwa so:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
So weiss ich immer womit ich es zu tun habe und kann die Variablen ohne Probleme so deklarieren:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
Und wenn du es irgendwann einmal zu einem sinnvollem Programm, welches länger als 5 Zeilen eigenes Code ist, schaffen solltest, wirst du es wahrscheinlich selber so machen. Natürlich, bei Copy&Paste braucht man sich keine Gedanken darüber zu machen - Autor hat es wahrscheinlich schon getan - also bleib ruhig bei kopieren.
Gast
#5685780
W.S. schrieb: > Selbstverständlich reicht es nicht aus, sowas wie goto zu verteufeln, > nein, man muß auch alle gängigen Typen umbenennen und alle Zahlen außer > 0 und 1 aus einem anständigen Programm entfernen und durch Bezeichner > ersetzen Du brauchst doch nur eine Rechtfertigung dafür, dass du in deinen Projekten aus Faulheit nicht jedes Bit einzeln mit Namen definierst, weil du ja auch die Hersteller-Header verteufelst... Dieses Tretminenfeld aus Makros ist zwar nicht schön, aber immer noch besser als Massen an Magic Numbers. W.S. schrieb: > Also: Beckmesser war die Knalltüte in Wagners Meistersingern Kennst du eigentlich nur diese eine Oper? Bist du daher einer von diesen Intellektuellen?
Marc V. schrieb: > Ausführliche Kommentare (auch schon bei der Deklaration der > Variablen/Konstanten) finde ich jedoch viel nützlicher. Grundsätzlich ein falscher Ansatz, aber ... nicht immer. Jedesmal wenn es einen juckt einen Kommentar zu formulieren sollte man zuvor überlegen, ob nicht der gleiche Informationsgewinn durch Umbenennen des Bezeichners möglich ist. Zieht man das durch, bleibt erstaunlich wenig übrig, das eines Kommentars bedarf und der Code wird viel leichter verständlich. doof:
1 | |
besser:
1 | |
Gast
#5685802
Marc V. schrieb: > Zusätzlich zu den sinnvollen Variablennamen setze ich bei Konstanten > immer ein c_ davor, etwa so:#define c_SOF 0xAA > #define c_EOF 0xA9 > > // Position in Buffer > #define c_RcvAdr 0x01 > #define c_SndAdr 0x02 > #define c_CmdTyp 0x03 > #define c_CmdLen 0x04 > #define c_DatBlk 0x05 > > #define c_DatBlkLen 0x3F // 63 Byt max > > So weiss ich immer womit ich es zu tun habe und kann die > Variablen ohne Probleme so deklarieren:typedef struct { > uint8_t Msg_SOF; > uint8_t RcvAdr; > uint8_t SndAdr; > uint8_t CmdTyp; > uint8_t CmdLen; > uint8_t DatBlk[c_DatBlkLen]; > } USART_RAM; > USART_RAM UartRam; // CRC/ChkSum und EOF werden danach gesendet Und warum nicht direkt Strukturen verwenden? > Und wenn du es irgendwann einmal zu einem sinnvollem Programm, > welches länger als 5 Zeilen eigenes Code ist, schaffen solltest, > wirst du es wahrscheinlich selber so machen. Dein Codefragment sieht aber genau so aus, als gäbe es nur einen sehr kleinen Kontext. Der einzige gemeinsame Nenner der 6 Konstanten (warum auch immer die bei 1 anfangen) ist das c_. Und genau das verwendest Du doch Deinen Worten nach auch woanders. > Natürlich, bei Copy&Paste braucht man sich keine Gedanken darüber > zu machen - Autor hat es wahrscheinlich schon getan - also bleib > ruhig bei kopieren. Hat das noch einen Bezug zu irgendwelchen Aussagen von W.S. hier?
Marc V. schrieb: > setze ich bei Konstanten > immer ein c_ davor, etwa so: > #define c_SOF 0xAA Die allgemein übliche Konvention für Macros ist es, deren Namen in Versalien zu schreiben. Deine "Konstanten" sind nämlich keine, sondern Macros. Wenn das eine Konstante sein soll, muss es so aussehen:
1 | |
A. S. schrieb: > Und warum nicht direkt Strukturen verwenden? Macht er doch, die Konstante (genauer: das #define) taucht als Anzahl in dem Array aus Strukturen auf, das er anlegt.
Gast
#5685900
Rufus Τ. F. schrieb: > A. S. schrieb: >> Und warum nicht direkt Strukturen verwenden? > > Macht er doch, die Konstante (genauer: das #define) taucht als Anzahl in > dem Array aus Strukturen auf, das er anlegt. wofür c_RcvAdr, wenn es nur offsetof RcvAdr ist? In den meisten fällen schreibt man doch eh X.RcvAdr. Und wenn man den Index braucht ... doppelt gemoppelt failed schneller.
Ich bezog mich hierauf:
1 | |
(nein, ein Array aus Strukturen ist das gar nicht, da hab' ich mich offensichtlich vertan) Wozu die anderen "Konstanten" gut sein sollen, hatte ich mir gar nicht angesehen.
Ich versteh gar nicht, warum hier so viel auf C++, class und struct rumgekaut wird, darum ging es dem OP doch gar nicht. "Variablen eindeutig benennen damit der Typ eindeutig ist" - eigentlich kann man sich die Frage selbst beantworten, indem man mal den Quellcode von einigen Open Source-Projekten überfliegt, die soetwas nutzen und sich daran orientieren: gängige Konvention ist wohl, dass dafür Präfixe verwendet werden, wenn auch in unterschiedlichen Ausformungen. Ich persönlich halte nicht viel davon. Letztlich kommt es, wie oft schon angesprochen, auch darauf an, was für das jeweilige Projekt vorgeschrieben ist. Für private Sachen kann man es dann halten, wie man will. Viel schlimmer als Variablen mit Präfixen zu versehen finde ich in C eher die Unart von vielen Bibliotheken, für die primitiven Typen eigene typdefs zu definieren. Statt mit etwas Einheitlichem wie uint32_t darf man sich dann mit UINT, uint, UINT32, U32, u4 etc. herumschlagen. Hier wäre es mir echt lieber, wenn nicht jeder das Rad neu erfinden bzw. älterer Code in dieser Hinsicht mal gewartet werden würde.
Gast
#5686211
Florian S. schrieb: > Viel schlimmer als Variablen mit Präfixen zu versehen finde ich in C > eher die Unart von vielen Bibliotheken, für die primitiven Typen eigene > typdefs zu definieren. Statt mit etwas Einheitlichem wie uint32_t Ich glaube das hat historischen Grund. Die stdint.h gibt es erst seit C99.
Stefanus F. schrieb: > Ich glaube das hat historischen Grund. Ja, vor allem sind manche Betriebssystem-APIs auch ziemlich alt; das von MS verwendete Namensschema (BYTE, WORD, DWORD etc.) ist bald 30 Jahre alt (ich hab' zwar noch nie ein Windows 2.x-SDK gesehen, aber das werden sie nicht für Windows 3.0 erst so erfunden haben, und das kam im Mai '90 raus).
Gast
#5686240
Carl D. schrieb: > Einfach nur die Mainstreamsprache zu hassen ist keine Leistung. Scheinbar irgendwie doch schon. Dem Hass liegt nämlich eine durch eigene Arbeit mit Blut, Schweiss und Tränen gewonnene Erkenntnisse zugrunde, zu der reine Lib-Zusammenleimer niemals gelangen werden... > Selbst > wenn man bei C die Freiheit hat sich Probleme einzufangen, Assembler ist > C darin haushoch überlegen. Das ist nach den Gesetzen der Informatik nicht wirklich so. Natürlich ist unbestritten, dass man in Assembler sehr leicht Fehler produzieren kann (Wer wüsste das besser als jemand wie ich, der sehr oft in Assembler programmiert o;) Aber: Der Unterschied zu C ist: Hier kann man nicht nur (fast) alle typischen Fehler eines Assemblerprogrammierers begehen (denn die stehen einem fast alle durch die mögliche Maschinennähe von C genauso frei zur Verfügung), man kann DARÜBER HINAUS auch noch Unmassen C-Fehler begehen. D.h.: Fehler in einer Abstraktionsschicht, die in Assembler schlicht nicht passieren können, weil diese Abstraktionsschicht dort überhaupt nicht existiert. Schonmal von Komplexitätsbetrachtungen gehört? Das ist eine sehr schönes Beispiel für eine nützliche Anwendung solcher Betrachtungen...
c-hater schrieb: > eigene Arbeit mit Blut, Schweiss und Tränen Wenn Du doch nur einfach C programmieren gelernt hättest, wäre Dir viel davon erspart geblieben.
c-hater schrieb: > Aber: Der Unterschied zu C ist: Hier kann man nicht nur (fast) alle > typischen Fehler eines Assemblerprogrammierers begehen (denn die stehen > einem fast alle durch die mögliche Maschinennähe von C genauso frei zur > Verfügung), man kann DARÜBER HINAUS auch noch Unmassen C-Fehler begehen. Die Wahrscheinlichkeit, dass ich einen halbwegs komplexen Ausdruck wie
1 | |
in Assembler falsch beschreibe, sind deutlich höher als in C. Selbst dann noch, wenn man Überläufe usw. berücksichtigt. Die Wahrscheinlichkeit, dass ich aus einem Array den falschen Wert lese, weil ich mich bei der Indexberechnung verhakle, ist in Assembler deutlich höher als in C. Und ja, ich habe schon einiges mit Assembler gearbeitet (und auch absichtlich). Es gibt Situationen, in denen will man Assembler. Das sind aber äußerst wenige und selbst dort ist C-Interoperabilität hilfreich.
A. S. schrieb: > kleinen Kontext. Der einzige gemeinsame Nenner der 6 Konstanten (warum > auch immer die bei 1 anfangen) ist das c_. Weil Offset 0 immer SOF ist. Und wenn du den Rest nicht verstehst (bzw. keinen gemeinsamen Nenner siehst), brauchen wir auch nicht weiter darüber zu diskutieren. A. S. schrieb: > wofür c_RcvAdr, wenn es nur offsetof RcvAdr ist? In den meisten fällen > schreibt man doch eh X.RcvAdr. Und wenn man den Index braucht ... Deswegen vielleicht:
1 | |
2 | |
3 | |
4 | |
? Ich bin mit solcher Bezeichnungsart bisher ganz gut gefahren, habe auch nach mehreren Monaten keine Probleme zu verstehen, was es bedeuten soll. Thomas M. schrieb: > Jedesmal wenn es einen juckt einen Kommentar zu formulieren sollte man > zuvor überlegen, ob nicht der gleiche Informationsgewinn durch > Umbenennen des Bezeichners möglich ist. Zieht man das durch, bleibt > erstaunlich wenig übrig, das eines Kommentars bedarf und der Code wird > viel leichter verständlich. Also, das stimmt bestimmt nicht, zumindest nicht für einigermassen komplexe Programe. Ich wollte schon unzählige Male beim ändern bzw. erweitern eines Programs klüger sein als beim schreiben, ein paar Bytes/Takte einsparen aber das hat sich ohne entsprechende Kommentare oft genug als ein Schuss nach hinten erwiesen. Wie gesagt, das alles mag Geschmacksache sein, nicht aber in einem Team - da fliegt man ohne entsprechend kommentierten Code ganz schnell raus. Und bei Variablen wie a, aa, aaa... erst recht.
Gast
#5686326
Rufus Τ. F. schrieb: > Wenn Du doch nur einfach C programmieren gelernt hättest, So nicht, mein Lieber. Er hat C gelernt. Aber C gelernt zu haben und es vernünftig benutzen zu können, ist etwa GANZ anderes, als diese Programmiersprache zu mögen oder gar zu lieben (oder noch schlimmer: sie zu verehren). Nee, mit etwas Abstand betrachtet, ist C eine zwar versatile, aber dennoch häßliche Programmiersprache, die eben auch ihren Benutzern die Freiheit läßt, ihre Quelltexte bis zur Unleserlichkeit zu verhunzen. Ja, das geht und man kriegt das ganz einfach auf die bürokratische Weise hin, indem man saublöde Zusatz-Regeln aufstellt, die das Übliche sind: Gut gemeint und damit auch hier das Gegenteil von gut gemacht. Tja, gut gemeint... Da setzen sich Leute hin, um sich sowas wie c_ für Konstanten per #define auszudenken (und meinen dazu "So weiss ich immer womit ich es zu tun habe") - oder noch anderen Schmonzes. Dieser Thread ist ne Sammlung davon. Aber wer sich schon daran macht, Regeln aufzustellen, der sollte diese auch zuende denken. Wenn man sowas wie #define c_ottokar 4711 fordert, um das Konstantenhafte zu dokumentieren, was legt man dann für ne echte Konstante fest? Rufus hat das ja schon thematisiert: const int c_i_echt_ottokar = 4711; So? Oder wie sonst? Wer Unterschiede so dokumentiert haben will, muß auch für alle im Sprachumfang erlaubten Fälle etwas Passendes ausdenken. An so einem Mini-beispiel sieht man deutlich, was für Pappnasen hier sich an Regulierungen versuchen. Alles Mumpitz, was man deutlich sehen kann, wenn man diese dummen Gedanken mal konsequent zuende denkt. Thomas M. schrieb: > doof:ulong i = 0; // Index für Dingse > besser:ulong dingsIdx = 0; O ha! Und du bist ernstlich der Ansicht, daß man aus dingsIdx mehr an Verständnis entnehmen kann als aus einen einfachen i ? Für lokale Zählindizes sind Namen wie i,j,k,l sehr brauchbar, denn sie halten die Ausdrücke kurz und haben auch nur einen Gültigkeitsbereich von nur wenigen Textzeilen. Hier mit Namen wie 'lokalerZaehlIndex' arbeiten zu wollen ist albern. Vielleicht sollten mal alle C-Programmierer nen Fortran-Kurs belegen. Dr. Sommer schrieb: > Kennst du eigentlich nur diese eine Oper? Bist du daher einer von diesen > Intellektuellen? Diese Oper ist leider hier die zuständige Instanz. Deswegen. Ich hätte mir durchaus hier mehr Leute mit Intellekt gewünscht, aber - nun ja - man kann ja leider nicht alles haben. W.S.
Gast
#5686346
Also ich liebe meine Familie und ich hasse den Mann, der mich 3 Monate lang für sich arbeiten liess ohne zu bezahlen. Der c_hater hat vermutlich weder eine Liebe noch eine Nemesis, deswegen fällt er hier so seltsam auf. Irgendwo braucht jeder sein Ventil.
Gast
#5686350
W.S. schrieb: > Ich hätte mir durchaus hier mehr Leute mit Intellekt gewünscht, aber - > nun ja - man kann ja leider nicht alles haben. Die Welt ist kein Wunschkonzert. Nicht jeder kann deiner kruden Weltsicht folgen.
Dr. Sommer schrieb: > Die Welt ist kein Wunschkonzert. Nicht jeder kann deiner kruden > Weltsicht folgen. Nun bin ich erst mal (wieder) überrascht, wieviele Beiträge sich zu so einem Blödsinn sammeln. Blödsinn, weil wenn privat, dann Jacke wie Hose...wenn Profi, dann gibt es eine bindende(!) Vorschrift, wie Programme geschrieben werden müssen!! Wenn nicht, dann reden wir von einer "Klitsche", die nicht besser als "privat" ist! Und hier melden sich offensichtlich Repräsentanten aller Kathegorien...zumindes die "Profis" hätte ich hier nicht erwartet :-) Gruß Rainer
Gast
#5686408
Marc V. schrieb: > Ich bin mit solcher Bezeichnungsart bisher ganz gut gefahren, > habe auch nach mehreren Monaten keine Probleme zu verstehen, was > es bedeuten soll. Das glaube ich Dir. Es wird nur noch einfacher, wenn Du Dir redundante defines sparst. Poste ein Beispiel und ich spendiere Dir eine Kiste Bier, wenn ich es ohne Redundanz nicht einfacher hinbekomme . Marc V. schrieb: > ch wollte schon unzählige Male beim ändern bzw. erweitern eines > Programs klüger sein als beim schreiben, ein paar Bytes/Takte einsparen > aber das hat sich ohne entsprechende Kommentare oft genug als ein > Schuss nach hinten erwiesen. Das sind aber 2 verschiedene Baustellen: Sinnvolle Namen statt Kommentare (darum ging es) Kommentieren von abgefahrenen Tricks (darum ging es nicht)
Rainer V. schrieb: > wenn Profi, dann gibt es eine bindende(!) Vorschrift, wie > Programme geschrieben werden müssen!! Wenn nicht, dann reden wir von > einer "Klitsche", die nicht besser als "privat" ist! Was mich an diesem Forum immer beeindruckt ist das Muster aus diesem Post: "Ich bin Profi und mache alles superprofessionell. Wenn ihr das weniger professionell macht, seid ihr doofe Noobs!" Und dann muss natürlich der nächste kommen und zeigen, dass er noch professioneller ist als das, weil er noch irgendeine wirre Maßnahme ergreift, bei der alle die das nicht machen doofe Noobs sind. Bis man bei irgendsoeinem absurden theoretischen Professionalitätsniveau angelagt ist, was mit der Realität nur noch wenig und mit der ursprünglichen Frage und Situation garantiert überhaupt nichts mehr zu tun hat. Nur damit jeder mal gezeigt hat, wie professionell er ist. Das lustige daran ist, dass diese Posts immer darauf aus sind, andere mit der eigenen Erfahrung zu beeindrucken. Diesen Zweck verfehlen sie aber zuverlässig bei allen Lesergruppen. Die tatsächlich erfahrenen Leute haben erfahrungsgemäß eine deutlich entspanntere Haltung zu vielen Dingen, und haben erkannt dass es meist viele Wege gibt, die zu einem vernünftigen Ergebnis führen. Die genaue Einhaltung eines einzelnen Konzepts ist dabei meist nicht so wichtig. Anders gesagt: An dem herummaulen was andere tun ist leicht. Schwieriger ist, konstruktiv darauf aufzubauen und ausgehend von der Situation des anderen einen pragmatischen Verbesserungsvorschlag zu machen.
Rufus Τ. F. schrieb: > Es ist bestens bekannt, daß Du Fan von "magic numbers" im Quelltext > bist, denn die lassen sich ja viel einfacher im Datenblatt finden. Es ist viel schlimmer: Diese "Magic Numbers by W.S." müssen für jeden ATmega/ATTiny bei einer Portierung auf einen Verwandten der AVR-Familie neu angepasst werden, weil die Bits öfter mal an anderen Positionen im Register stecken. Unnötige Arbeit, wenn man die entsprechenden Preprocessor-Konstanten wie z.B. COM0A0 verwendet. Allerdings kann man da auch auf die Nase fliegen, da sie nicht immer nur innerhalb desselben Registers "wandern", sondern manchmal - aber glücklicherweise selten - auch (je nach AVR) das Register wechseln. Deshalb hatte ich vor ein paar Jahren mal ein Projekt "Registersichere Anwendung von Flags" vorgeschlagen. Leider ist es aus Zeitmangel nur bei einem Konzept geblieben. Es wäre nämlich eine Menge Arbeit gewesen, für alle AVRs sämtliche Register und deren Flags bzw. Bitgruppen vollständig und registersicher zu beschreiben. Mit diesem Werkzeug wäre es dann aber vollkommen egal, in welchem Register die Bits überhaupt stecken. Siehe auch: Beitrag "Re: AVR-Register als Bitfields"
W.S. schrieb: > Tja, gut gemeint... Da setzen sich Leute hin, um sich sowas wie c_ für > Konstanten per #define auszudenken (und meinen dazu "So weiss ich immer > womit ich es zu tun habe") - oder noch anderen Schmonzes. Mag für dich und andere Möchtegern- und Copy&Paste Experten Schmonz sein, für mich ist es nicht. W.S. schrieb: > auch zuende denken. Wenn man sowas wie > > #define c_ottokar 4711 > > fordert, um das Konstantenhafte zu dokumentieren, was legt man dann für > ne echte Konstante fest? Rufus hat das ja schon thematisiert: > > const int c_i_echt_ottokar = 4711; > > So? Oder wie sonst? Wie du nicht weisst, wird const ins Flash geschrieben, #define aber ist einfach eine Anweisung für Präprozessor. Einen Array mit festen Werten schreibe ich als:
1 | |
2 | |
3 | |
und kann auch daraus lesen. So etwas kann man aber mit const nicht machen:
1 | |
2 | |
mit #define dagegen geht das ohne Probleme. Etwas, was mit #define definiert wurde, kann mit #undef wieder rückgängig gemacht werden. Wenn du mit Copy&Paste aufhörst, wirst du das (kaum wahrscheinlich aber immerhin zu 0,0001% möglich) auch verstehen.
Frank M. schrieb: > Deshalb hatte ich vor ein paar Jahren mal ein Projekt "Registersichere > Anwendung von Flags" vorgeschlagen. Leider ist es aus Zeitmangel nur bei > einem Konzept geblieben. Es wäre nämlich eine Menge Arbeit gewesen, für > alle AVRs sämtliche Register und deren Flags bzw. Bitgruppen vollständig > und registersicher zu beschreiben. Könnte man mittlerweile per xslt aus den XML-Beschreibungen machen. Beim ATmega128RFA1 (und seinen Nachfolgern) hatten wir sowas ins offizielle Headerfile in der avr-libc reingepackt, aber das hat in der restlichen AVR-Welt innerhalb Atmel keinen Anklang gefunden. Seit sie nun all ihren eigenen Device-Support nur noch über ihre "device packs" verteilen (und damit eigene Headerfiles ausliefern, die nicht denen des avr-libc-Projekts entsprechen), dürfte das gänzlich den Bach runtergegangen sein.
Gast
#5686459
W.S. schrieb: > Aber wer sich schon daran macht, Regeln aufzustellen, > der sollte diese auch zuende denken. Warum denn das? Worauf gründet sich diese Regel? Hast Du die etwa selbst aufgestellt, ohne sie ganz zu Ende zu denken? Es ist sehr sinnvoll, nur häufig auftretende Problemfälle durch explizit formulierte Regeln zu beseitigen. Andernfalls löst man eben Probleme, die sich gar nicht stellen -- dafür gibt es das schöne Wort "Überregulation". > Wenn man sowas wie > > #define c_ottokar 4711 > > fordert, um das Konstantenhafte zu dokumentieren, was > legt man dann für ne echte Konstante fest? Rufus hat > das ja schon thematisiert: > > const int c_i_echt_ottokar = 4711; Das ist ja wohl eine perverse (="verdrehte") Weltsicht. Das, was Du als "echte Konstante" bezeichnest, ist technisch eine vorbelegte Variable. > Thomas M. schrieb: >> doof:ulong i = 0; // Index für Dingse >> besser:ulong dingsIdx = 0; > > O ha! Und du bist ernstlich der Ansicht, daß man aus > dingsIdx mehr an Verständnis entnehmen kann als aus > einen einfachen i ? Machst Du Witze? Wenn eine Routine mit Koordinaten, Codeworten (die aus zwei verschachtelten Koordinaten bestehen) und Ternärvektoren (die ihrerseits aus einem Codewort und einer Maske bestehen) operiert, dann möchte ich schon gern auf einen Blick sehen, ob jetzt die nächste Koordinate, das nächste Codewort oder der nächste Ternärvektor gemeint ist. Das ist nämlich nicht GANZ dasselbe. Ich verwende durchaus auch i,j,k für Indizes und Laufvariablen, aber das nur, wenn aus dem Zusammenhang offensichtlich ist, worauf sich dieser Index bezieht. > Für lokale Zählindizes sind Namen wie i,j,k,l sehr > brauchbar, denn sie halten die Ausdrücke kurz und > haben auch nur einen Gültigkeitsbereich von nur wenigen > Textzeilen. Hier mit Namen wie 'lokalerZaehlIndex' > arbeiten zu wollen ist albern. Überhaupt nicht. Wenn man Daten aus einem Quelldatenfeld liest, sie verarbeitet und dann im Ergebnis der Verarbeitung in eines von mehreren Ergebnisfeldern schreibt, dann möchte man schon gern wissen, welcher Index in welches Feld zeigt. Es gibt mehr als for-Schleifen, und auch in zwei geschachtelten Schleifen kann man mehr als zwei Indizes benötigen. Und -- nein, dass lässt sich NICHT immer vermeiden. Manche Algorithmen SIND eben einfach kompliziert. > Ich hätte mir durchaus hier mehr Leute mit Intellekt > gewünscht, aber - nun ja - man kann ja leider nicht > alles haben. Nun ja. Intellekt liegt im Auge des Betrachters...
A. S. schrieb: > Sinnvolle Namen statt Kommentare (darum ging es) Ich wiederhole mich ungern, aber dem TO kann man nur sagen, was Profis machen oder HiWis! Da sich hier lustigerweise sowohl Profis, als auch HiWis die Klinke in die Hand geben...was soll man da sagen...ich fand meinen Beitrag zur Mausefalle unterhaltsamer! Gruß Rainer
Rainer V. schrieb: > wenn Profi, dann gibt es eine bindende(!) Vorschrift, wie > Programme geschrieben werden müssen!! Wenn nicht, dann reden wir von > einer "Klitsche", die nicht besser als "privat" ist! Ach was erzählst du da für einen Unsinn... Professionell heißt nur, dass man damit Geld verdient und sagt nichts über die Qualität aus. Eine wie auch immer geartete, "bindende Vorschrift, wie Programme geschrieben werden müssen" ist ein untrügliches Zeichen dafür, dass man es entweder mit inkompetenten Idioten oder stark regulierten Märkten zu tun hat. Bei uns gibt es stattdessen mehrere Code-Reviews. Marc V. schrieb: > Wie du nicht weisst, wird const ins Flash geschrieben, #define aber > ist einfach eine Anweisung für Präprozessor. Auch "const" wird nicht ins Flash geschrieben, wenn es nicht ins Flash geschrieben werden muss. Stichwort Compiler-Optimierung. Marc V. schrieb: > So etwas kann man aber mit const nicht machen: > const uint8_t c_DatBlkLen = 0x3F; // 63 Byt max > uint8_t DatBlk[c_DatBlkLen]; > mit #define dagegen geht das ohne Probleme. Auch das ist seit C99 schlicht falsch. Stichwort Variable Length Array. Ein typischer Marc.
A. S. schrieb: > Das glaube ich Dir. Es wird nur noch einfacher, wenn Du Dir redundante > defines sparst. Poste ein Beispiel und ich spendiere Dir eine Kiste > Bier, wenn ich es ohne Redundanz nicht einfacher hinbekomme . Nein, umgekehrt. Ich spendiere dir eine Kiste Bier, wenn du mir die Redundanz in meinem Beitrag zeigst. A. S. schrieb: > Das sind aber 2 verschiedene Baustellen: > > Sinnvolle Namen statt Kommentare (darum ging es) Nun, so sehe ich das bestimmt nicht. Sinnvole Namen und Kommentare sowohl für Variablen, als auch innerhalb des Programms. Und es geht natürlich um Programme die länger als ein paar Zeilen sind, mehr als ein Dutzend Variablen haben und wesentlich komplizierter als BlinkLed Beispiel sind. Da sind mehrere Dutzend includes, mit mehreren Tausenden von Linien. Wenn man da etwas ändern muss und dazu erst die Routine xxyyzz finden muss, um zu sehen was diese Routine überhaupt tut, anstatt dies gleich aus Kommentar zu sehen oder vielleicht sogar aus dem Namen, z.B: PutDateTimeToI2C(). Genauso ist es mit Variable xxyyzz. Das dies alles auch unter der Maus angezeigt wird, ändert nichts an der Sache.
Gast
#5686538
S. R. schrieb: > Auch das ist seit C99 schlicht falsch. Stichwort Variable Length Array. Die können aber nicht global/statisch sein. C++ hat übrigens echte Konstanten, die kann man auch für globale Arrays verwenden oder für die Definition weiterer Konstanten. Konstanten landen nicht notwendigerweise separat im Flash, die werden auch ggf. direkt in die Instruktionen kodiert. Allgemein braucht man in C++ sehr selten Makros, und das ist ein Vorteil...
S. R. schrieb: > Auch "const" wird nicht ins Flash geschrieben, wenn es nicht ins Flash > geschrieben werden muss. Stichwort Compiler-Optimierung. Für mich bedeutet const eine readonly Variable, die demzufolge irgendwo im Flash abgelegt werden muss. Mit #define wird irgendetwas definiert, ob das ein Ausdruck, String oder schlicht ein Wert ist, ist absolut egal. > Marc V. schrieb: >> So etwas kann man aber mit const nicht machen: >> const uint8_t c_DatBlkLen = 0x3F; // 63 Byt max >> uint8_t DatBlk[c_DatBlkLen]; >> mit #define dagegen geht das ohne Probleme. > > Auch das ist seit C99 schlicht falsch. Stichwort Variable Length Array. Ahem. Kompiliere das mal bitte, so wie es da steht. Soviel ich und mein Compiler es wissen, geht das nur wenn man Array lokal deklariert, nicht aber wenn es global deklariert wird. > Ein typischer Marc. Eher ein typischer svenska.
Gast
#5686559
Marc V. schrieb: > Für mich bedeutet const eine readonly Variable, die demzufolge irgendwo > im Flash abgelegt werden muss. Für dich vielleicht. Für z.B. den GCC aber nicht. Der merkt wenn sie nirgends verändert wird (typischerweise via "static const") und nimmt sie als fix an, und kodiert die Werte in die Immediates der Instruktionen direkt hinein. Marc V. schrieb: > Mit #define wird irgendetwas definiert, ob das ein Ausdruck, String oder > schlicht ein Wert ist, ist absolut egal. Ja, eine dumme Textersetzung. Das ist ein sehr grobes Werkzeug, da kann man schnell mal daneben hauen...
Gast
#5686565
Ich habe viel zu viel Zeit damit verbracht, Fehler zu finden, die dadurch getarnt waren, dass z.B. ein unsigned char u16BlaBlubb hieß, weil irgendein Profi früher beim Copy&Paste geschlampt hatte. Jahre später lief u16BlaBlubb aufgrund anderer Änderungen dann über, was laut Variablenname nicht sein konnte. Die ungarischen Schniepel waren in dem Projekt "aus Sicherheitsgründen" vorgeschrieben. Gegen die Funktion mit 1000 Zeilen und 10 verschachtelten Ebenen und die 20 unnötigerweise am Funktionsanfang auf Vorrat deklarierten Variablen, zwischen denen sich u16BlaBlubb versteckt hat, hatten die Richtlinien natürlich nichts einzuwenden.
Dr. Sommer schrieb: > Marc V. schrieb: >> Mit #define wird irgendetwas definiert, ob das ein Ausdruck, String oder >> schlicht ein Wert ist, ist absolut egal. > > Ja, eine dumme Textersetzung. Das ist ein sehr grobes Werkzeug, da kann > man schnell mal daneben hauen... Stimmt, allerdings kann man an vielen Stellen in einem Programm ganz schnell daneben hauen... Der einzige Nachteil von #define ist meiner Meinung nach die fehlende Prüfung auf ev. Fehler, deswegen mag die definition von Makros fehlerträchtig sein, aber Deklarationen von einfachen Positionen im Buffer bestimmt nicht.
Gast
#5686588
Marc V. schrieb: > Ich spendiere dir eine Kiste Bier, wenn du mir die Redundanz in > meinem Beitrag zeigst. A. S. schrieb: > wofür c_RcvAdr, wenn es nur offsetof RcvAdr ist? In den meisten fällen > schreibt man doch eh X.RcvAdr. Und wenn man den Index braucht ... > doppelt gemoppelt failed schneller. Deshalb fragte ich fairer Weise nach einem sinnvollen Beispiel.
Gast
#5686597
Marc V. schrieb: > Der einzige Nachteil von #define ist meiner Meinung nach die fehlende > Prüfung auf ev. Fehler Das ist ein ziemlicher Nachteil. Dazu kommt dass die keinen Scope haben und dass man keine Pointer drauf bilden kann. Wenn man C++ nutzt gibt es keinen Grund diese Nachteile in Kauf zu nehmen; man nimmt einfach Konstanten und alles ist besser.
Marc V. schrieb: >> Auch "const" wird nicht ins Flash geschrieben, wenn es nicht ins Flash >> geschrieben werden muss. Stichwort Compiler-Optimierung. > > Für mich bedeutet const eine readonly Variable, > die demzufolge irgendwo im Flash abgelegt werden muss. Das mag für dich so sein, der Compiler sieht das anders. >> Marc V. schrieb: >>> So etwas kann man aber mit const nicht machen: >>> const uint8_t c_DatBlkLen = 0x3F; // 63 Byt max >>> uint8_t DatBlk[c_DatBlkLen]; >>> mit #define dagegen geht das ohne Probleme. >> >> Auch das ist seit C99 schlicht falsch. Stichwort Variable Length Array. > > Ahem. > Kompiliere das mal bitte, so wie es da steht.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Geht prima, wo ist dein Problem? > Soviel ich und mein Compiler es wissen, geht das nur wenn man Array > lokal deklariert, nicht aber wenn es global deklariert wird. Dein geposteter Code enthält kein main(), lässt sich also nicht kompilieren. Ich habe mir nur die Freiheit genommen, eins einzubauen. :-) >> Ein typischer Marc. > Eher ein typischer svenska. Mir ging es darum, dich darauf hinzuweisen, dass deine beiden Aussagen maximal Halbwissen sind. Das stört vor allem, weil du immer in Absolutismen schreibst und selbstverständlich niemals Unrecht hast. Ein "sowas kann man nicht machen" ist falsch, wenn man es eben doch meistens machen kann. Und mit Aussagen wie "wie du nicht weißt, gilt X" blamierst du dich vor allem dann, wenn X nicht uneingeschränkt gilt. Und genau das ist typisch. Damit wäre ich dann wieder raus, streitet euch mal weiter. :-)
A. S. schrieb: > A. S. schrieb: >> wofür c_RcvAdr, wenn es nur offsetof RcvAdr ist? In den meisten fällen >> schreibt man doch eh X.RcvAdr. Und wenn man den Index braucht ... >> doppelt gemoppelt failed schneller. > > Deshalb fragte ich fairer Weise nach einem sinnvollen Beispiel. Marc V. schrieb: > Deswegen vielleicht: > union { > USART_RAM sRam; > uint8_t sbuff[5 + c_DatBlkLen + 3]; > } Uart_un; > ? Falls ich:
1 | |
anstatt:
1 | |
verwende, habe ich deutlich mehr an vielen Stellen zu schreiben. Deklarieren tue ich es dagegen nur einmal ;)
Gast
#5686627
Marc V. schrieb: > falls ich: sbuff[offsetof(UartRam, CmdTyp)] anstatt: sbuff[c_CmdTyp] > verwende, habe ich deutlich mehr an vielen Stellen zu schreiben. > Deklarieren tue ich es dagegen nur einmal ;) Und warum nicht sRam.CmdTyp? Wie gesagt, Fetzen bringen wenig. Zumal es trotzdem nicht rechtfertigt, Struktur und define parallel zu pflegen.
S. R. schrieb: >> Ahem. >> Kompiliere das mal bitte, so wie es da steht. > $ cat test.c > int main() > { > const char x = 0x3F; > char test[x]; > > return 0; > } > $ gcc test.c > $ ./a.out > $ > > Geht prima, wo ist dein Problem? Sure. Und so ?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
S. R. schrieb: > Mir ging es darum, dich darauf hinzuweisen, dass deine beiden Aussagen > maximal Halbwissen sind. Das stört vor allem, weil du immer in > Absolutismen schreibst und selbstverständlich niemals Unrecht hast. Tja, eigentlich geht es mir so mit dir.
Joern DK7JB .. schrieb: > Wie benennt ihr eure Variablen eindeutig in der Programmiersprache C > damit eindeutig ist welcher Typ verwendet worden ist? Gibt es da eine > bewährte Methode oder erfindet da jeder Programmierer das Rad neu? Mir ist nicht ganz klar, wie man auf die Idee kommt, dass es sinnvoll wäre dies zu tun. Wie andere schon gesagt haben - jeder moderne Editor zeigt einem den Variablentyp an, wenn man z.B. kurz mit der Maus drübergeht. Was immer sinnvoll ist, sind selbstsprechende Namen für Variablen und Funktionen. Man liest den Namen und schon weiß man um was es geht. Beispiele: Vehicle_speed RoomTemperature TransmitBuffer[] display_speed() temperature_to_Fahrenheit() isBufferFull()
A. S. schrieb: > Und warum nicht sRam.CmdTyp? Wie gesagt, Fetzen bringen wenig. Weil sbuff ein Array ist und da ist sbuff[c_CmdTyp] für mich irgendwie logischer. sRam ist eine Struktur, da passt sRam.CmdTyp schon. > Zumal es trotzdem nicht rechtfertigt, Struktur und define parallel zu > pflegen. Mag sein, aber die sind gleich untereinander deklariert, zusammen mit allen anderen Variablen fur RS485. Die Namen sind vielleicht nicht ganz passend gewählt, aber das ganze funktionert seit vielen Jahren so, warum jetzt ändern ?
S. R. schrieb: > Ach was erzählst du da für einen Unsinn... > Professionell heißt nur, dass man damit Geld verdient und sagt nichts > über die Qualität aus. Eine wie auch immer geartete, "bindende > Vorschrift, wie Programme geschrieben werden müssen" ist ein > untrügliches Zeichen dafür, dass man es entweder mit inkompetenten > Idioten oder stark regulierten Märkten zu tun hat. Bei uns gibt es > stattdessen mehrere Code-Reviews. Also seid ihr Klitsche nach meinem Verständniss! Und es sagt erst mal auch gar nichts über die (welche) Qualität aus, was wem möglicherweise vorgeschrieben wird. Aber wenn mehr als 2 Mann/Frau an einer Software basteln, dann sind nicht nur die Übergabeparameter festgeschrieben, sondern auch der Stil der Programmierarbeit überhaupt! Wenn ich von einem Fuzzi 3 Mal in der Woche Module bekomme, die Fehler erzeugen, dann schau ich doch mal in dessen Quellcode und wehe, der ist anders als im Pflichtenheft geschrieben! Und bitte verzeih', "Code-Review" hört sich für mich an wie "Therapeutensitzung" Und klar heisst professionell, dass man Geld verdient...was sonst? Gruß Rainer
Rainer V. schrieb: > S. R. schrieb: > Bei uns gibt es >> stattdessen mehrere Code-Reviews. > > Also seid ihr Klitsche nach meinem Verständniss! Und es sagt erst mal > auch gar nichts über die (welche) Qualität aus, was wem möglicherweise > vorgeschrieben wird. Aber wenn mehr als 2 Mann/Frau an einer Software > basteln, dann sind nicht nur die Übergabeparameter festgeschrieben, > sondern auch der Stil der Programmierarbeit überhaupt! Wenn ich von > einem Fuzzi 3 Mal in der Woche Module bekomme, die Fehler erzeugen, dann > schau ich doch mal in dessen Quellcode und wehe, der ist anders als im > Pflichtenheft geschrieben! > Und bitte verzeih', "Code-Review" hört sich für mich an wie > "Therapeutensitzung" Genau! Bäm! Du Noob! Ich Profi! Überhaupt sind nur Leute mit Pflichtenheft Profis! Und Leute mit anderen etablierten Verfahren, wie Reviews, sind Noobs, weil ich als Profi das nicht mache und deshalb kann das gar nicht professionell sein! Mehrere verschiedene Möglichkeiten, professionell zu arbeiten, sind grundsätzlich nicht vorstellbar: sonst ist das Feld der Professionalität ja vielleicht gar nicht total geordnet, und dann kann ich gar nicht ganz oben in der Hackordnung stehen. Wie gesagt, dieses Muster ist hier im Forum echt typisch und es hat noch nie zu einer gewinnbringenden Diskussion geführt, ever. Es nervt nur alle: die Beteiligten und die Leser gleichermaßen. In der Softwareentwicklung ist das besonders krass, weil es ohne Übertreibung hunderte solcher Vorgaben gibt, die von weiten Kreisen als ein absolutes Muss gehandelt sind, anderen hingegen völlig unbekannt sind. Deshalb kann man sich da trefflich stundenlang anmaulen, wer der größere Noob ist weil er keine Versionskontrolle // keine Reviews // kein Pflichtenheft // keine Style Guide // keine Dokumentations-Guideline // kein Scrum // kein whaaatever macht. Projekte wie der Code für die Mondrakete beweisen aber z.B., dass man sehr wohl ohne Versionskontrollsystem gute Software entwickeln kann ... Man wird hier nicht dadurch zum Profi, dass man möglichst viele Punkte auf der Buzzword-Liste abhakt. Weniger ist manchmal sogar mehr.
S. R. schrieb: > Marc V. schrieb: >> Wie du nicht weisst, wird const ins Flash geschrieben, #define aber >> ist einfach eine Anweisung für Präprozessor. > > Auch "const" wird nicht ins Flash geschrieben, wenn es nicht ins Flash > geschrieben werden muss. Stichwort Compiler-Optimierung. Das geht aber nur, wenn es static ist. Sonst muss sie im Flash stehen, da eine andere Übersetzungeinheit sie referenzieren könnte. > Marc V. schrieb: >> So etwas kann man aber mit const nicht machen: >> const uint8_t c_DatBlkLen = 0x3F; // 63 Byt max >> uint8_t DatBlk[c_DatBlkLen]; >> mit #define dagegen geht das ohne Probleme. > > Auch das ist seit C99 schlicht falsch. Stichwort Variable Length Array. Die gibt es aber aus offensichtlichen Gründen nur bei lokalen Variablen. Tatsächlich gibt es in C gar keine echten Konstanten. #define ist die beste Annäherung daran. Deshalb wird es auch so oft dafür verwendet. Ein const int ist keine Konstante, sondern eine Variable, die man nicht ändern darf. Und ja, das macht einen Unterschied. Beispiel:
1 | |
2 | |
Das führt in gcc zu folgendem Fehler:
1 | |
2 | |
3 | |
Sven B. schrieb: > Genau! Bäm! Du Noob! Ich Profi! Überhaupt sind nur Leute mit > Pflichtenheft Profis! Mann, dich in einem Vorstellungsgespräch...göttlich... und Betriebssystem "Hello World"... Kleiner Mann mit peinlich kleinem Hut... Rainer
Rainer V. schrieb: > Mann, dich in einem Vorstellungsgespräch...göttlich... Hmm, meinst du, es wäre besser, dir in einem Vorstellungsgespräch gegenüber zu sitzen? Wenn ich es mir aussuchen kann, würde ich wohl Sven jederzeit den Vorzug geben. Leute mit Dogma mag ich nicht (weder als Chef noch als Mitarbeiter). Ich habe schon an so vielen verschiedenen Projekten mitgearbeitet, dass ich mir die Flexibilität leisten muss, nicht auf einen coding style festgefahren zu sein. Auch ohne geschriebene coding guides kann man konsistenten Code produzieren, wenn man nur will. („Ungarische“ Notation war aber, von paar Win32-Syscalls in AVRDUDE abgesehen, bislang zum Glück noch nicht dabei.)
Sven B. schrieb: > Projekte wie der Code für die Mondrakete beweisen aber z.B., dass man > sehr wohl ohne Versionskontrollsystem gute Software entwickeln kann ... > Man wird hier nicht dadurch zum Profi, dass man möglichst viele Punkte > auf der Buzzword-Liste abhakt. Weniger ist manchmal sogar mehr. Na ja, heutzutage kann man tatsächlich nicht mehr professionell ohne Versionskontrolle entwickeln. Alleine schon wenn man gegenüber dem Gutachter reproduzierbar nachweisen muss, welcher SW-Stand wann wie zur Zulassung gebracht werden soll oder wenn man eben Änderungen (nach-)dokumentieren muss. Gehört nicht ohne Grund zum "Joel Test" ;-) https://www.joelonsoftware.com/2000/08/09/the-joel-test-12-steps-to-better-code/
Rolf M. schrieb: >> Auch "const" wird nicht ins Flash geschrieben, wenn es nicht ins Flash >> geschrieben werden muss. Stichwort Compiler-Optimierung. > > Das geht aber nur, wenn es static ist. Sonst muss sie im Flash stehen, > da eine andere Übersetzungeinheit sie referenzieren könnte. In der Theorie ja. In der Praxis gibt es auch link-time-optimization (gcc: -flto). Damit funktionieren solche Optimierungen auch über die Grenzen von Übersetzungseinheiten hinweg.
Axel S. schrieb: >> Das geht aber nur, wenn es static ist. Sonst muss sie im Flash stehen, >> da eine andere Übersetzungeinheit sie referenzieren könnte. > > In der Theorie ja. In der Praxis gibt es auch link-time-optimization > (gcc: -flto). Damit funktionieren solche Optimierungen auch über die > Grenzen von Übersetzungseinheiten hinweg. Mit switches kann man vieles anders machen und verdrehen, fragt sich nur ob das auch sinnvoll ist. Bei einem Teamprojekt steht der switch bei einem Kollegen so, bei anderen wiederum anders und schon werden aus selbem Code 4 verschiedene Versionen kompiliert - bei einem funktioniert es, bei anderem (der zufälligerweise gerade seine Routine geändert hat) nicht und dann geht die Sucherei los...
Gast
#5687060
Marc V. schrieb: > Axel S. schrieb: >>> Das geht aber nur, wenn es static ist. Sonst muss sie im Flash stehen, >>> da eine andere Übersetzungeinheit sie referenzieren könnte. >> >> In der Theorie ja. In der Praxis gibt es auch link-time-optimization >> (gcc: -flto). Damit funktionieren solche Optimierungen auch über die >> Grenzen von Übersetzungseinheiten hinweg. > > Mit switches kann man vieles anders machen und verdrehen, fragt sich > nur ob das auch sinnvoll ist. > Bei einem Teamprojekt steht der switch bei einem Kollegen so, bei > anderen wiederum anders und schon werden aus selbem Code 4 verschiedene > Versionen kompiliert... Ernsthaft? Etwas überspitzt gefragt: Redet ihr in diesem "Team" auch miteinander? Es gibt Dinge die sollte man im Team festlegen.
Gast
#5687065
Marc V. schrieb: > Bei einem Teamprojekt steht der switch bei einem Kollegen so, bei > anderen wiederum anders Die Switches sollten im Makefile, IDE-Projekt o.ä. stehen und daher bei allen gleich sein. Ein Grund, Projektdateien eben doch in der Versionskontrolle einzuchecken, was IMO unberechtigterweise so verpönt ist.
Gast
#5687076
Dr. Sommer schrieb: > Marc V. schrieb: >> Bei einem Teamprojekt steht der switch bei einem Kollegen so, bei >> anderen wiederum anders > > Die Switches sollten im Makefile, IDE-Projekt o.ä. stehen und daher bei > allen gleich sein. Ein Grund, Projektdateien eben doch in der > Versionskontrolle einzuchecken, was IMO unberechtigterweise so verpönt > ist. Wie genau meinst du das? Ist die Versionskontrolle allgemein oder Projektdateien im VCS verpönt?
Gast
#5687077
PS: Der Code sollte natürlich bei allen Compiler-Switches korrekt funktionieren (außer bei solchen welche die Standard-Konformität beeinflussen wie -std=gnu99 oder -ffast-math), aber optimale Ergebnisse darf man ohne die richtigen Optimierungen nicht erwarten. Und in C++ ist das alles wie gesagt sowieso kein Problem, weil das Konstanten echt konstant sind.
Gast
#5687084
mh schrieb: > Wie genau meinst du das? Ist die Versionskontrolle allgemein oder > Projektdateien im VCS verpönt? Projektdateien im VCS einchecken ist verpönt. Wenn die Projekdateien keine absoluten Pfade o.ä. nutzen ist das aber IMO völlig in Ordnung. Selbst wenn ein Teammitglied unbedingt eine andere IDE nutzen möchte (was bei manchen Embedded Plattformen sowieso nicht geht, weil es nur 1 IDE dafür gibt), hat man so immerhin ein "Referenz"-Setup an welches man sich halten kann. Insbesondere bei Embedded-Plattformen kann das Anlegen & Konfigurieren von Projekten ziemlich kompliziert sein - da spart das Einchecken der Projektdatei eine Menge Arbeit.
mh schrieb: > Ernsthaft? Natürlich, > Etwas überspitzt gefragt: Redet ihr in diesem "Team" auch > miteinander? Ja, wir reden miteinander. > Es gibt Dinge die sollte man im Team festlegen. Und es gibt Dinge, die soll man nicht mit Gewalt und ohne Grund ändern, nur damit man beweist, dass irgendein Beitrag in uC.net nicht stimmt. So etwas nennt sich Korinthenkackerei und es gibt ein paar Leute hier, die genau das immer wieder tun, nur um zu beweisen wie klug und allwissend sie sind und wie unwissend die anderen. Dass das genau nichts zum Thema beiträgt und dem TO in keiner Weise hilft, berührt diese Experten überhaupt nicht, Hauptsache die anderen werden als unwissend/halbwissend dargestellt... P.S. Aussage: Mercedes ist ein verkehrssicheres Fahrzeug. Behauptung: Ja, aber wenn man die Reifen auf 0,5 bar aufpumpt und dann mit 200Km/h auf der Autobahn fährt, stimmt das überhaupt nicht... Schlussfolgerung: Die obige Aussage ist falsch und derjenige der das behauptet, hat überhaupt keine Ahnung von Fahrzeugen und fahren.
Gast
#5687164
Egon D. schrieb: > Es ist sehr sinnvoll, nur häufig auftretende Problemfälle > durch explizit formulierte Regeln zu beseitigen. Andernfalls > löst man eben Probleme, die sich gar nicht stellen -- dafür > gibt es das schöne Wort "Überregulation". Dieses schöne Wort heißt in der Mechanik und woanders "Überbestimmt" und ist ein Designfehler. Aber hier handelt es sich gar nicht darum, sondern es handelt sich um Vollständigkeit. Das ist was grundlegend Anderes. Und wenn du "nur häufig auftretende Problemfälle" mit Regeln versiehst, was ist dann deine Regel wert? Garnichts. Entweder ist eine Regel eine Regel oder sie ist nur heiße Luft - und sollte deshalb schlichtweg ignoriert werden. >> const int c_i_echt_ottokar = 4711; > > Das ist ja wohl eine perverse (="verdrehte") Weltsicht. > Das, was Du als "echte Konstante" bezeichnest, ist > technisch eine vorbelegte Variable. Du redes Unsinn. Das Obengenannte ist eine Konstante. Und zwar eine echte, die bei einem µC im Flash landet. Im Gegensatz dazu ist alles, was man per #define macht, eine Textersetzung. Und das was man mit typedef macht, ist ein Alias. Versuche du erstmal das logische Denken und das Verwenden korrekter Wörter zu erlernen, bevor du hier große Töne redest. W.S.
Gast
#5687197
W.S. schrieb: > Du redes Unsinn. Das Obengenannte ist eine Konstante. Und zwar eine > echte, die bei einem µC im Flash landet. Nein. Wozu haben wir das gerade diskutiert? Lesen bildet!
W.S. schrieb: >> Das ist ja wohl eine perverse (="verdrehte") Weltsicht. >> Das, was Du als "echte Konstante" bezeichnest, ist >> technisch eine vorbelegte Variable. > > Du redes Unsinn. Das Obengenannte ist eine Konstante. Nein, ist es technisch gesehen nicht. C kennt in diesem Sinne keine Konstanten, es ist eine Variable, bei dem Versuche, ihren Wert zur Laufzeit zu ändern, vom Compiler abgewiesen werden. C++ kennt echte Konstanten, deshalb darf man sowas dort auch zur Definition der Größe eines (beliebigen) Arrays benutzen, was man in C nicht darf:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
> Und zwar eine > echte, die bei einem µC im Flash landet. Primär landet bei einem µC natürlich alles im Flash. Aber obige Definition besagt noch lange nicht, dass für das Datum explizit Flash reserviert wird. Der Wert kann genauso gut als Direktwert in einen Operanden gepackt werden, oder der Compiler benutzt dafür ein Register, von welchem er weiß, dass dort genau dieser Wert gerade drin steht. > Im Gegensatz dazu ist alles, > was man per #define macht, eine Textersetzung. Das hat keiner in Frage gestellt.
Gast
#5687228
Jörg W. schrieb: > Nein, ist es technisch gesehen nicht. C kennt in diesem Sinne keine > Konstanten, es ist eine Variable, bei dem Versuche, ihren Wert zur > Laufzeit zu ändern, vom Compiler abgewiesen werden. Jörg, das mag am PC drin sein, schließlich kennt Pascal solche "typisierten Konstanten" ja auch - und am PC liegt schlichtweg alles im RAM, weswegen man bei Pascal auf sowas sogar schreibend zugreifen kann, wenn man das tatsächlich will. Aber bei allen Mikrocontrollern, die ich kenne, landet so eine "Variable" tatsächlich im Flash und das war's. Es ist technisch gesehen, eine hart in Silizium gegossene Variable, die dadurch zu einer echten Konstanten wird, weil sie als "Ding" wirklich existiert und weil wirklich jeder Schreibversuch zum Fault oder zu nix führt - auch wenn da kein Compiler meckern würde. Ich habe sowas reichlich in den USB-Treibern, siehe: const byte DeviceDescriptor[] = { .... Nochmal: Wenn jemand schreibt #define joerg 99 X = joerg + Y; dann wird in den allermeisten Fällen "joerg" niemals in der Firmware tatsächlich auftauchen, sondern als Teil eines Maschinenbefehls zu Y addiert werden. Wenn jeman aber const int joerg = 99; schreibt, dann gibt es mit Sicherheit innerhalb der Firmware eine zumindest 16 bittige Zahl mit dem Wert 99. Und die kann adressiert werden wie alle anderen Dinge. Der Knackpunkt liegt darauf, daß ein #define überhaupt keine Konstante erzeugt, sondern eine schlichte Textersetzung macht. Der Compiler kriegt davon nur die finale Zahl mit. W.S.
Gast
#5687246
W.S. schrieb: > Aber bei allen Mikrocontrollern, die ich kenne, landet so eine > "Variable" tatsächlich im Flash und das war's. Dann probier doch mal einen STM32F103 aus. Aus
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
macht der GCC hier
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Da ist nirgendwo eine adressierbare Konstante. Sowohl Adresse als auch Bitmaske landen direkt als Immediates in den Instruktionen. Genau so als hätte man ein Makro verwendet. Nur hat man so die diversen Nachteile des Makros vermieden. Der Code wurde mit -Os -mpure-code kompiliert. Letzteres ist nötig, um dem GCC eine andere Optimierung abzugewöhnen, bei welcher er Literal Pools nutzt; der gezeigte Assembler-Code ist schneller aber größer als ohne diese Option. Zu Demonstrationszwecken ist es aber hier interessant, die Version ohne Literal Pool zu sehen.
@ Teilnehmer der Konstantendiskussion: Ihr redet teilweise aneinander vorbei, weil ihr nicht dazuschreibt, über welche Sorte von Konstanten ihr redet. In der Softwaretechnik lässt sich der Konstantenbegriff in (mindestens) vier Kategorien unterteilen: - Literale (literals) - Compilezeit-Konstanten (compile-time constants) - Compilezeit-konstante Ausdrücke (compile-time constant expressions) - Nichtüberschreibbare Variablen (immutable variables, Obermenge der Compilezeit-Konstanten) Zusätzlich kann man Konstanten jeder dieser drei Kategorien in C per Makrodefinition neue Namen geben, die damit ebenfalls Konstanten der jeweiligen Kategorie repräsentieren. In der Mathematik, von wo der Begriff "Konstante" entlehnt wurde, wird er nochmals etwas anders genutzt, ebenso in der Physik. Da viele Softwareentwickler einen mathematischen und/oder physikalischen Hintergrund haben, wird der Begriff oft auch in diesen Bedeutungen verwendet. Wenn ein Softwareentwickler also einfach nur "Konstante" sagt, können damit sieben verschiedene Dinge gemeint sein. In 6/7 aller Fälle muss eine Diskussion zwischen zwei Softwareentwicklern in einem Internet- forum über Konstanten deswegen unweigerlich zu einem nicht konstanten, sondern eskalierenden Streit führen ;-)
W.S. schrieb: > const byte DeviceDescriptor[] = Erstens ist ein Array schon mal was ganz anderes, zweitens hast du auch hier zumindest bei einer recht prominenten µC-Architektur unrecht: da der AVR für Operationen aus dem Flash andere Befehle braucht als für Operationen aus dem RAM, werden selbst string literals (die schon seit C89 "immutable" waren) dort im RAM untergebracht und nur aus dem Flash initialisiert. Normale Arrays oder structs werden ebenfalls im RAM untergebracht, auch wenn sie "const" markiert sind. Der Compiler wirft das zwar in die section ".rodata":
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
… aber dem Linker bleibt nichts anderes übrig, als das dann in den RAM zu packen und aus dem Flash zu initialisieren:
1 | |
2 | |
3 | |
4 | |
5 | |
(Adressen ab 0x800000 werden bei der AVR-GCC-Tolchain als RAM behandelt, Flash ist ab 0.) So pauschal, wie du das behauptest, passt es eben nicht. Von Fachbegriffen sehen wir mal ganz ab („Verwenden korrekter Wörter“), denn spätestens beim C-Standard wirst du dich ziemlich schnell auf ungewolltes Glatteis begeben …
Yalu X. schrieb: > In 6/7 aller Fälle muss > eine Diskussion zwischen zwei Softwareentwicklern in einem Internet- > forum über Konstanten deswegen unweigerlich zu einem nicht konstanten, > sondern eskalierenden Streit führen ;-) :-))
Gast
#5687416
Joern DK7JB .. schrieb: > Wie benennt ihr eure Variablen eindeutig in der Programmiersprache C > damit eindeutig ist welcher Typ verwendet worden ist? Gibt es da eine > bewährte Methode oder erfindet da jeder Programmierer das Rad neu? Ungarische Notation, war lange bei Microsoft Hausideologie mit dem bekannten Ergebnis. Seit Sie das lassen scheint es besser zu laufen, kann aber auch Zufall sein. Auf jeden Fall hat es nichts gebracht. Hab ich auch eine Zeitlang gemacht weil Anfänger. Inzwischen lasse ich es, kostet unnötig Gehirnschmalz und Zeit und lenktab. Zusätzlich wird die Software überdefinert was Änderungen erschwert. Zum lernen aber war es Klasse. Hat das Typenproblem bei mir besser eingebrannt. Kann jedem empfehlen ungarisch anzufangen und es sein zu lassen wenn man C besser kann.
Gast
#5687493
W.S. schrieb: >>> const int c_i_echt_ottokar = 4711; >> >> Das ist ja wohl eine perverse (="verdrehte") Weltsicht. >> Das, was Du als "echte Konstante" bezeichnest, ist >> technisch eine vorbelegte Variable. > > Du redes Unsinn. Das mag der Ungebildete so sehen... > Das Obengenannte ist eine Konstante. Du hast Schwierigkeiten mit der Exaktheit, kann das sein? Ich habe nicht bestritten, dass das eine Konstante ist. Ich habe darüber gespottet, dass Du das einzige, was technisch nicht zwingend eine Konstante, sondern eine vorbelegte Variable ist, als "echte Konstante" bezeichnest. > Und zwar eine echte, die bei einem µC im Flash landet. Variablen, vorbelegte Variablen und Konstanten gibt es schon wesentlich länger als Flash-Speicher; das, was Du versuchst, ist ein Anachronismus. > Im Gegensatz dazu ist alles, was man per #define macht, > eine Textersetzung. Richtig. Und deshalb sind die Sprachelemente, die davon betroffen sind, zur Laufzeit GARANTIERT konstant -- was man von vorbelegten Variablen nicht behaupten kann. > Versuche du erstmal das logische Denken und das Verwenden > korrekter Wörter zu erlernen, bevor du hier große Töne > redest. Das gebe ich gern zurück und ergänze: Versuche, auf das Herabsetzen Deines Kontrahenten zu verzichten -- es schadet Dir selbst mehr als ihm.
HyperMario schrieb: > Ungarische Notation ... > Hab ich auch eine Zeitlang gemacht weil Anfänger ... > Zum lernen aber war es Klasse. Hat das Typenproblem bei mir besser > eingebrannt. Kann jedem empfehlen ungarisch anzufangen und es sein zu > lassen wenn man C besser kann. Au weia. Ist das die masochistische Extremversion von "Lernen durch Schmerz"? Klar lernt man Sachen besonders nachhaltig, wenn der Irrtum mit Schmerzen verbunden war. Aber ich würde nicht so weit gehen, Schmerzen als unabdingbar für einen Lerneffekt anzusehen.
mh schrieb: >> Mit switches kann man vieles anders machen und verdrehen, fragt sich >> nur ob das auch sinnvoll ist. > > Ernsthaft? Etwas überspitzt gefragt: Redet ihr in diesem "Team" auch > miteinander? Es gibt Dinge die sollte man im Team festlegen. Nein, das sind nur rhetorische Tricks, um nicht feststellen zu müssen, dass die Welt ein bisschen komplizierter ist. Genauso wie das hier: Marc V. schrieb: > Aussage: > Mercedes ist ein verkehrssicheres Fahrzeug. > > Behauptung: > Ja, aber wenn man die Reifen auf 0,5 bar aufpumpt und dann mit > 200Km/h auf der Autobahn fährt, stimmt das überhaupt nicht... > > Schlussfolgerung: > Die obige Aussage ist falsch und derjenige der das behauptet, > hat überhaupt keine Ahnung von Fahrzeugen und fahren. Der erste Teil der Schlussfolgerung ist richtig. Der zweite Teil ist Unsinn zur Ablenkung. Eine wunderschöne rhetorische Figur, inhaltlich ist der Pfeil leider an der Dartscheibe vorbeigeflogen, aber es sollte ja nur zeigen, dass ... was eigentlich? Ein typischer Marc eben.
Axel S. schrieb: > Au weia. Ist das die masochistische Extremversion von "Lernen durch > Schmerz"? Klar lernt man Sachen besonders nachhaltig, wenn der Irrtum > mit Schmerzen verbunden war. Aber ich würde nicht so weit gehen, > Schmerzen als unabdingbar für einen Lerneffekt anzusehen. Es gibt ja Dinge, von denen behauptet wird, dass man sie mal selber falsch gemacht haben muss, um wirklich zu verstehen, warum es falsch ist. Ist wie mit dem Kind, dem auch erst dann wirklich klar wird, warum es vom Herd wegbleiben soll, wenn es sich mal die Finger an der Herdplatte verbrannt hat. Ob das jetzt für die Microsoft'sche ungarische Notation auch gilt, sei aber mal dahingestellt. Ich hab noch nie verstanden, wozu das gut sein soll und es deshalb auch noch nie benutzt.
Frage an die Profis von einem reinen Hobbyisten: Redet ihr bei den Namenskonventionen von den im Verhältnis wenigen globalen Variablen, oder wendet ihr das auch auf lokale Variablen an? Eigentlich sind bei mir gefühlt 95% der Funktionen kürzer als zwei Fensterhöhen, dass der komplette Scope jeder Variablen fast immer komplett sichtbar ist. Und dann beschränke ich mich meist auf einfache, kurze und sprechende Namen. (Damit ist dann 'g' mein einziger echter Präfix, nämlich für globale Variablen. Ansonsten halt Abkürzungen nObj, iObj etc., aber das sind ja keine echten Präfixe, sondern Namensteile.)
Walter T. schrieb: > Frage an die Profis von einem reinen Hobbyisten: Redet ihr bei den > Namenskonventionen von den im Verhältnis wenigen globalen Variablen, > oder wendet ihr das auch auf lokale Variablen an? > > Eigentlich sind bei mir gefühlt 95% der Funktionen kürzer als zwei > Fensterhöhen, dass der komplette Scope jeder Variablen fast immer > komplett sichtbar ist. Und dann beschränke ich mich meist auf einfache, > kurze und sprechende Namen. Ich gehe nach dem Prinzip vor: Je größer der Scope, desto aussagekräftiger sollten die Namen sein. > (Damit ist dann 'g' mein einziger echter Präfix, nämlich für globale > Variablen. Bei mir gehören globale Variablen - so sie denn existieren - zu einem bestimmten Modul, und dann ist der Name des Moduls der Präfix.
Rolf M. schrieb: > Ich gehe nach dem Prinzip vor: Je größer der Scope, desto > aussagekräftiger sollten die Namen sein. Hier auch so. Eine strikte Regulierung von Namen haben wir nicht. Die gängige Konvention, dass Makronamen (zumindest eigene, nicht aus fremdem Code "geerbte") GROSS geschrieben werden, wird jedoch eingehalten. Namenspräfixe für globale Namen (sowohl Variablen als auch Funktionen) werden vorzugsweise nach Subsystem vergeben, damit deren Namen nicht mit normalem Anwendercode (der diese Subsysteme natürlich kennt) kollidieren können. Für modulinterne Namen ist das nicht notwendig, die können keine Namenskollision verursachen.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.