Datum:
Hallo, ich bin zufällig auf folgende Syntax gestoßen, hier ein Beispiel:
PORTE = "\0x47\0x11\0x08\0x15\0xAB\0xCD\0xEF\0x77"[n & 0x07]; |
Hier wird eine kleine Tabelle mit char's angelegt, die nur lokal gebraucht wird und deshalb nicht einmal eine Namen bekommt. Meine Frage, wie kann man das für short oder long int schreiben? Oder geht das vielleicht nur für char?
Datum:
> Und was soll der Quatsch? Ensure a job for life ;-) http://thc.org/root/phun/unmaintain.html
Datum:
Peter Zz schrieb: > Hallo, ich bin zufällig auf folgende Syntax gestoßen, hier ein Beispiel: >
> PORTE = "\0x47\0x11\0x08\0x15\0xAB\0xCD\0xEF\0x77"[n & 0x07]; > |
> Hier wird eine kleine Tabelle mit char's angelegt, die nur lokal > gebraucht wird und deshalb nicht einmal eine Namen bekommt. Vergiss das ganz schnell wieder. Ich kann mich an den Thread erinnern, aus dem du das raus hast. Das ist eine auf den ersten Blick überraschende Kuriosität der C-Syntax. Wenn du das real einsetzt, sollte man dich mit dem nassen Fetzen ein paar mal rund ums Büro jagen. Man muss nicht jeden 'Unfug' benutzen, nur weil er theoretisch möglich ist.
Datum:
Peter Zz schrieb: > Hier wird eine kleine Tabelle mit char's angelegt, die nur lokal > gebraucht wird und deshalb nicht einmal eine Namen bekommt. Man darf auch lokale Tabellen anlegen, die lesbar sind, ohne diese verrückte Schreibweise. Außerdem verschwendet diese Schreibweise Speicherplatz, da ein 0-Byte angefügt wird. Und Vorsicht, je nach Compiler kann es passieren, daß die Tabelle bei jedem Aufruf erst neu angelegt wird! Daher werden konstante Arrays in der Regel außerhalb einer Funktion definiert. Peter
Datum:
Karl Heinz Buchegger schrieb: > Wenn du das real einsetzt, sollte man dich mit dem nassen Fetzen ein > paar mal rund ums Büro jagen. OK, ich werd es nicht einsetzen, Pfadfinderehrenwort :-)
Datum:
nur aus Interesse, wieso die VerUndung mit 0x07? Das führt doch nur dazu, dass für zB n=2 der selbe Eintrag genutzt wird wie für n=10, richtig?
Datum:
oder anders ausgedrückt, alle 8 Durchläufe die Tabelle von Neuem genutzt wird.
Datum:
Peter Zz schrieb: > Karl Heinz Buchegger schrieb: >> Wenn du das real einsetzt, sollte man dich mit dem nassen Fetzen ein >> paar mal rund ums Büro jagen. > > OK, ich werd es nicht einsetzen, Pfadfinderehrenwort :-) ich nehme sowas gelegentlich, und schäme mich nicht mal dafür!
Datum:
Klaus Wachtler schrieb: > ich nehme sowas gelegentlich, und schäme mich nicht mal dafür! In was für ner Klitsche arbeitest Du, dass dort MISRA-C ein Fremdwort ist? ;-)
Datum:
blubb schrieb: > nur aus Interesse, wieso die VerUndung mit 0x07? > > Das führt doch nur dazu, dass für zB n=2 der selbe Eintrag genutzt wird > wie für n=10, richtig? Ja. Da die Tabelle aber nur 8 (Nutz*-) Elemente enthält, dürfte das Verhalten ohne die Verundung zu interessanten Nebeneffekten führen. *) die abschließende \0 macht 9 draus, aber die bleibt hier ungenutzt.
Datum:
blubb schrieb: > oder anders ausgedrückt, alle 8 Durchläufe die Tabelle von Neuem genutzt > wird. Jep. Im Original ging es genau darum. Das war eine Schrittmotoransteuerung mit Halbschritten und der String sind in Wirklichkeit die Codes mit denen die diskreten Ausgangstreiber geschaltet wurden. (Wenn mich meine Erinnerung nicht trügt) n war einfach nur eine Variable, die mit den Schritten erhöht bzw. verringert wurde.
Datum:
Mark Brandis schrieb: > Klaus Wachtler schrieb: >> ich nehme sowas gelegentlich, und schäme mich nicht mal dafür! > > In was für ner Klitsche arbeitest Du, dass dort MISRA-C ein Fremdwort > ist? ;-) Meistens in meiner eigenen. Jedenfalls nie in einer Bude, in der nach MISRA gearbeitet wird - das ist m.E. Blödsinn. Nichts gegen ordentliches Programmieren, aber wenn man seine Programmierer für so debil hält, daß sie nicht mit C umgehen können (was ja sein kann), dann soll man nicht C nehmen sondern BASIC, und nicht von C alles wegkürzen in der Hoffnung, daß BASIC rauskommt.
Datum:
Nur um mal ein konstruktives Vorbild zu geben, wie man sowas knapp aber deutlich lesbarer gestaltet:
const short treiber_ansteuerung[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; [...snip...] PORTE = treiber_ansteuerung[n & 7]; |
Eine Zeile mehr, dafür selbstdokumentierend, d.h. ggf. spart man sich den separaten Kommentar dafür. Und man kann es auf dem AVR auf diese Weise auch im Flash-Speicher speichern, wenn man das möchte (Stichwort PROGMEM).
Datum:
Klaus Wachtler schrieb: > Jedenfalls nie in einer Bude, in der nach > MISRA gearbeitet wird - das ist m.E. Blödsinn. > Nichts gegen ordentliches Programmieren, aber wenn man seine > Programmierer für so debil hält, daß sie nicht mit C umgehen können (was > ja sein kann), dann soll man nicht C nehmen sondern BASIC, und nicht von > C alles wegkürzen in der Hoffnung, daß BASIC rauskommt. DANKE, DANKE, DANKE!
Datum:
Klaus Wachtler schrieb: > Nichts gegen ordentliches Programmieren Vieles, was in C möglich ist und vom Compiler akzeptiert wird, geht am Thema "ordentlich programmiert" meilenweit vorbei. Wenn dem nicht so wäre, gäbe es den IOCCC nicht :-) http://www.ioccc.org/ Außerdem gilt: Da, wo mehrere Entwickler an der gleichen Software arbeiten, sind vernünftige Programmierrichtlinien unumgänglich. Wenn jeder seinen C oder C++ Code "frei nach Schnauze" schreiben darf, dann gute Nacht Projekt! In einem Code Review würde man die obige Zeile, so wie Karl Heinz Buchegger schon bemerkt hat, um die Ohren gehauen bekommen. Und womit? Mit Recht.
Datum:
Mark Brandis schrieb: > sind vernünftige Programmierrichtlinien unumgänglich. Jaja, aber du lobpriesest zuvor MISRA, während du jetzt von "vernünftigen Programmierrichtlinien" schreibst. MISRA enthält viele Dinge, die eigentlich für jedermann relativ selbstverständlich sind. Aber es enthält auch Forderungen, die voll und ganz in Klaus' Aussage reinpassen, dass man halt nur solche Leute in C programmieren lassen sollte, die die Sprache auch kennen, statt alle die zu beschneiden, die wirklich damit umgehen können. Beispielsweise darf laut MISRA eine Schleife höchstens ein break und kein continue haben. Beides kann aber durchaus (bei sorgfältiger Benutzung) sehr sinnvoll sein und helfen, Code optimal zu formulieren. Wenn man in so einer Situation ist und dann MISRA einhalten muss, führt es dazu, dass man für den Schleifenabbruch eine Hilfsvariable hinzufügen muss, die im besten Fall den gleichen Effekt wie mehrere break hat, im schlimmsten Fall zu mehr Code führt. Übersichtlicher wird es dadurch kaum. Gleichfalls für continue: statt die Schleife mit continue zu wiederholen, muss man eine zusätzliche Schachtelungstiefe für ein weiteres "if not" einfügen, um den Rest des Schleifenkörpers nicht mehr auszuführen. Über die Unsinnigkeit derartiger Forderungen hat sich Donald Knuth bereits 1974 in seinem Aufsatz "Structured Programming with go to Statements" ausgelassen. Auch über die Sinnhaftigkeit des Verbots, Gleitkommazahlen auf Gleichheit oder Ungleichheit zu testen, kann man gut streiten: bei allen heute üblichen Gleitkommadarstellungen hat die 0 ein genau definiertes Bitmuster. Dieses Muster wird insbesondere garantiert erzeugt während der Initialisierung einer Variablen. Damit ist ein Test wie:
float offset; ... void dosomething(void) { ... if (offset == 0.0) { /* offset has not been assigned yet */ ... offset = calculate_soemthing(); // which can never yield 0.0 again } } |
durchaus sinnvoll und wohl definiert. In MISRA ist das aber nicht zugelassen, da man Gleitkommazahlen generell nicht auf Gleichheit testen darf. p.s.: Real Programmers can write FORTRAN in any language. :-)
Datum:
Im Endeffekt kann eine Firma Programmierrichtlinien festlegen, wie sie es will. Solange sie eben als sinnvoll erachtet werden. Aber sie muss eben auch festlegen, nach welchen Richtlinien Code erstellt werden soll - wenn sie dies versäumt, handelt sie unprofessionell. Jörg Wunsch schrieb: > Auch über die Sinnhaftigkeit des Verbots, Gleitkommazahlen auf > Gleichheit oder Ungleichheit zu testen, kann man gut streiten Das Problem bei dem Vergleich auf 0.0 ist doch, dass z.B. 0.000001 hinreichend nahe an 0.0 liegt. Wenn die Differenz sehr gering ist, ist es aber eher unsinnig, den Vergleich als "false" zu werten. Deshalb: Nicht auf einen einzelnen Wert vergleichen, sondern ein akzeptables Delta definieren und auf einen Bereich [Sollwert-Delta; Sollwert+Delta] vergleichen. Das ist meines Wissens nach der Sinn hinter dieser Forderung.
Datum:
Mark Brandis schrieb: > Die Intention dahinter ist meines Erachtens nach eine andere. Kann ja sein, aber das Verbot des Vergleichs ist "required" laut MISRA, sodass die von mir oben geschilderte Situation dort verboten ist. Ich muss mir also als Programmierer dann extra noch ein Flag hinlegen, mit dem ich ermittle, ob der Wert bereits initial gesetzt worden war oder nicht. > Das Problem bei dem Vergleich auf 0.0 ist doch, dass z.B. 0.000001 > hinreichend nahe an 0.0 liegt. Kann ja sein. Wenn mich eine hinreichend kleine Differenz interessiert, schreibe ich als Programmier natürlich nicht einen Test auf != 0.0, sondern einen auf fabs(x) < epsilon. Wenn mich aber interessiert, ob der Wert jemals bereits gesetzt worden ist, ist das nicht die Lösung. Ich habe mir das nur als eins von einigen sinnlosen Details aus MISRA rausgepickt, weil es mir gerade unter die Finger kam, als ich die Schwarte aufgeklappt habe. Es gibt ein paar solcher Dinge da drin. Aber wie ich schon schrieb, der überwiegende Teil der MISRA- Regeln ist durchaus sinnvoll und entspricht dem, was ordentliche Programmierer auch von sich aus machen würden. Mit einem style guide hat das Ding übrigens nichts zu tun: sowas wie die Lage der Klammern, Einrückungsniveaus und dergleichen werden darin nicht geregelt. In einer Firma will man sowas in der Regel aber (bis zu einem nicht allzu hohen Detailgrad) auch geregelt haben.
Datum:
Zur ursprünglichen Frage: Peter Zz schrieb: > Meine Frage, wie kann man das für short oder long int schreiben? Beispiel für short:
short lookup(int n) { return (short []){ 314, 159, 265, 358, 979, 323, 806 }[n]; } |
Ich würde aber von dieser Methode, Lookup-Tabellen anzulegen, ebenfalls abraten, zumindest in C/C++. Der Hauptgrund: Peter Dannegger schrieb: > Und Vorsicht, je nach Compiler kann es passieren, daß die Tabelle bei > jedem Aufruf erst neu angelegt wird! Arrays mit konstantem Inhalt lege ich deswegen grundsätzlich statisch an. Was die Lesbarkeit betrifft, würde ich das Konstrukt nicht völlig verdammen. Letztendlich ist die Zeile
x = (short []){ 314, 159, 265, 358, 979, 323, 806 }[n]; |
ein C-Ausdruck von ähnlicher Komplexität wie
x = (short)((x11 + x12 + x13 + x21 + x22 + x23 + y) * n);
|
Wenn man das erste Beispiel so schriebe
static short table[] = { 314, 159, 265, 358, 979, 323, 806 }; x = table[n]; |
müsste man das zweite konsequenterweise so schreiben:
int sum = x11 + x12 + x13 + x21 + x22 + x23 + y; x = (short)(sum * n); |
Das kann man machen, muss es IMHO aber nicht.