Forum: Compiler & IDEs Kleine Tabelle anlegen


von Peter Z. (Gast)


Lesenswert?

Hallo, ich bin zufällig auf folgende Syntax gestoßen, hier ein Beispiel:
1
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?

von Kölner (Gast)


Lesenswert?

Und was soll der Quatsch?

von Krapao (Gast)


Lesenswert?

> Und was soll der Quatsch?

Ensure a job for life ;-)
http://thc.org/root/phun/unmaintain.html

von Karl H. (kbuchegg)


Lesenswert?

Peter Zz schrieb:
> Hallo, ich bin zufällig auf folgende Syntax gestoßen, hier ein Beispiel:
>
1
> PORTE = "\0x47\0x11\0x08\0x15\0xAB\0xCD\0xEF\0x77"[n & 0x07];
2
>
> 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.

von Peter D. (peda)


Lesenswert?

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

von Peter Z. (Gast)


Lesenswert?

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  :-)

von Mark B. (markbrandis)


Lesenswert?


von blubb (Gast)


Lesenswert?

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?

von blubb (Gast)


Lesenswert?

oder anders ausgedrückt, alle 8 Durchläufe die Tabelle von Neuem genutzt 
wird.

von Klaus W. (mfgkw)


Lesenswert?

ja, damit wird ein Überlauf vermieden.

von Klaus W. (mfgkw)


Lesenswert?

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!

von Mark B. (markbrandis)


Lesenswert?

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? ;-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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.

von Sam P. (Gast)


Lesenswert?

Nur um mal ein konstruktives Vorbild zu geben, wie man sowas knapp aber 
deutlich lesbarer gestaltet:
1
const short treiber_ansteuerung[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2
3
4
[...snip...]
5
6
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).

von Sven P. (Gast)


Lesenswert?

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!

von Mark B. (markbrandis)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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:
1
float offset;
2
3
...
4
void dosomething(void)
5
{
6
   ...
7
   if (offset == 0.0) { /* offset has not been assigned yet */
8
     ...
9
     offset = calculate_soemthing(); // which can never yield 0.0 again
10
   }
11
}

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. :-)

von Mark B. (markbrandis)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Zur ursprünglichen Frage:

Peter Zz schrieb:
> Meine Frage, wie kann man das für short oder long int schreiben?

Beispiel für short:
1
short lookup(int n) {
2
  return (short []){ 314, 159, 265, 358, 979, 323, 806 }[n];
3
}

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
1
  x = (short []){ 314, 159, 265, 358, 979, 323, 806 }[n];

ein C-Ausdruck von ähnlicher Komplexität wie
1
  x = (short)((x11 + x12 + x13 + x21 + x22 + x23 + y) * n);

Wenn man das erste Beispiel so schriebe
1
  static short table[] = { 314, 159, 265, 358, 979, 323, 806 };
2
3
  x = table[n];

müsste man das zweite konsequenterweise so schreiben:
1
  int sum = x11 + x12 + x13 + x21 + x22 + x23 + y;
2
3
  x = (short)(sum * n);

Das kann man machen, muss es IMHO aber nicht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.