Hi, ich hab hier grad ein Listing mit ner Zeile dich ich nicht kapiere. #define MAX 8 int add(int i) { return (i+1) == MAX ? 0 : i+1; } Versteh nur Bahnhof und hab noch keine Lösung gefunden thx dennis
#define MAX 8 -> Definiert eine Konstante MAX mit Wert 8 int add(int i) { return (i+1) == MAX ? 0 : i+1; } ist, glaube ich , so zu verstehen: int add(int i) { if (i+1) = MAX then return 0 else return i+1 } aber meine C-Kenntnisse sind eher grottig.
Hallo das gleiche mit einer if: #define MAX 8 int add(int i) { if (i+1 == MAX) return 0; else return i+1; } Hoffe das dir das hilft
ich schreibs mal mit anderen Worten auf: falls der Aufrufparameter der Funktion 'add' schon 8 ist, dann gib 0 zurück, andernfalls den um eins erhöhten Aufrufparameter. Vermute mal dieser Code (im Wahrsten Sinne des Wortes) stammt aus einem Programm welches sich mit Ringspeichern beschäftigt.
>aber meine C-Kenntnisse sind eher grottig. Wie sind dann meine wenn du das schon entziffern kannst >Hoffe das dir das hilft Sicher hilft mir das. Danke an Euch beide dennis
Hi, ich erlaub mir mal, das Ganze in etwas leichter lesbaren, aber equivalenten Code zu "übsersetzen": #define MAX 8 int add(int i) { if(i+1==MAX) return 0; else return i+1; }
Ergibt das nachher dann eigentlich identischen Code oder gibts da dann noch Unterschiede in der Codegröße oder Ausführungsgeschwindigeit?
Puh, gute Frage. Ich glaube (Achtung: glauben != wissen), dass da identischer Maschinencode erzeugt wird. Kann aber u. A. compilerabhängig sein. Am besten probierst du beide Varianten aus, und siehst dir danach das Assembler-Listing an. Das Ergebnis würde mich auch interessieren.
mal 'ne andere Frage: Würde return ((i+1) % MAX); also eine Operation Modulo MAX nicht das gleiche bewirken (außer bei Aufrufen mir Werten > MAX)? Auch hier wäre dann die Frage nach Codegröße und Ausführungsgeschwindigkeit. Oder hat der Programmierer des obigen Codes nur seine Unkündbarkeit im Sinn ;-)
>Oder hat der Programmierer >des obigen Codes nur seine Unkündbarkeit im Sinn ;-) Gute Frage, nächste Frage. Is aber ne gute Idee. Muß ich mal testen
jetzt wäre es interessant ob da der Compiler das gleiche macht....: return ((i+1) % MAX);
hm die Modulo Variante dauert aber länger, da hier eine division gemacht wird. Bei MAX = 8 würde ich zwar sagen dass er statt einer Division shifts macht, aber wenn MAX was anderes als 8 ist, dann muss die Divisions Routine her (Abziehen, inkrementieren.. Rest)
#define MAX 8 int add(int i) { return (i+1) == MAX ? 0 : i+1; } Ich sags mal so: add(0) ergibt 1 add(1) ergibt 2 ... add(5) ergibt 6 add(6) ergibt 7 add(7) ergibt 0 add(8) ergibt 9 add(9) ergibt 10 -------------------- Das "return ((i+1) % MAX)" sieht aber so aus: add(0) ergibt 1 ... add(6) ergibt 7 add(7) ergibt 0 add(8) ergibt 1 add(9) ergibt 2 Feadi
Wenn ich gerade mal (AVR) Compiler spiele, würde ich aus "(i+1) % MAX" (mit MAX = 8) folgende zwei Befehle machen: inc r16 andi r16, 0x07 Fertig. Eine Division braucht man da nicht! Die andere Lösung mit Vergleich und Sprung wird mindestens doppelt so lang. Aber wenn die Funktion nicht ständig in einer Schleife aufgerufen wird, macht sich der Geschwindigkeitsunterschied wohl kaum bemerkbar.
@Simon: Das von Christian passt schon. Das kann man so auch aufrufen wenn man erst bis 5 gezählt hat....
> int add(int i) > { > return (i+1) == MAX ? 0 : i+1; > } So programmieren nur Angeber, die anderen unbedingt zeigen wollen, dass sie Ahnung von C haben.
Also das würde ich jetzt nicht behaupten. So wie ich das jetzt sehe nachdem ich ein buch und ein paar Tutorials gelesen hab ist das durchaus ne reguläre Syntax. Das wäre Angeben for(;P("\n").R-;P("|"))for(e=3DC;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);
Oder noch schlimmer : Im code 1000 Makros verwenden, die im makefile definiert werden.
So wie dennis sehe ich das auch. Wer mal "angeberischen" C-Code sehen will, kann unter www.ioccc.org nachsehen. Für den Rest der Welt gehört der ternäre Operator ?: zu C dazu, wie auch die if-Entscheidung. Ein Vorteil des return-?:-Konstrukts ist die platzsparende Schreibweise, welches die lesbarkeit ERHÖHT! Vergleichen wir das mal mit einem Autofahrer. Dieser nähere sich einem Stoppschild. "Hui" sagt er, "dass kann ich nicht." und fährt lieber dreimal mehr rechts und viermal links um an dasselbe Ziel zu kommen. Was würde wohl ein Beifahrer davon halten? Gruß Marco -
Um mal dein Beispiel aufzugreifen:
Was würde der Beifahrer denken, wenn der Autofahrer erstmal 10min am
Verkehrsschild halten müsste, um zu entziffern, dass es ein Stoppschild
ist...
Der ternäre Operator ? gehört natürlich zu C dazu, so wie alle anderen
Terme in diesem Ausdruck auch. Aber die Kombination macht es
unleserlich. Wir diskutieren hier ja nicht darüber, ob das syntaktisch
korrekt ist oder nicht.
> return (i+1) == MAX ? 0 : i+1;
was bindet dabei mehr? Das "==" oder der "?"-Operator? Eine Klammer
mehr würde da vieles deutlicher machen...
----, (QuadDash).
Ich hab mal gelesen "C ist wie Geschichte in der Schule. Um es zu können muß man auswendig lernen". Wenn man sich die Syntax so anschaut muß ich dem Recht geben. Rein aus der Syntax kann man nicht wirklich auf die Funktion rückschließen. Anderen Sprachen sind "sprechender"
@---- Eben dass meine ich. Wer C gelernt hat, braucht keine 10min für das Stoppschild. Dass es Prioritäten gibt, sollte man wissen, zur Not auch nur, wo sie stehen. In der Tat würde eine Klammer mehr die Lesbarkeit für Anfänger fördern. i+1 == MAX ? 0 : i+1 <=> ((i+1) == MAX) ? 0 : (i+1) Und wenn man bei so einer Sache knobeln muss, ist das meiner Meinung nach eine der besten Möglichkeiten zu lernen. Gruß Marco -
Das Stoppschild ist aber so verschleiert, dass man es erst nach 10min als solches erkennt, selbst wenn man weiss wie eins aussieht... ;-) > Und wenn man bei so einer Sache knobeln muss, ist das meiner Meinung > nach eine der besten Möglichkeiten zu lernen. Nein, das ist die Garantie, dass Fehler passieren. Der Code ist für den Menschen geschrieben und muß damit einfach lesbar sein. 80% aller C-Programmierer glauben sie seien überdurchschnittlich gut, die restlichen 20% denken sie seien weit überdurchschnittlich. > In der Tat würde eine Klammer mehr die Lesbarkeit für Anfänger > fördern. Das klingt leicht überheblich. (Auch wenns wahrscheinlich nicht so gemeint war). > Dass es Prioritäten gibt, sollte man wissen, zur Not auch > nur, wo sie stehen. Nein, man sollte Unklarheiten vermeiden, dann spart man sich auch das nachschauen. ----, (QuadDash).
>> Dass es Prioritäten gibt, sollte man wissen, zur Not auch nur, wo >> sie stehen. > Nein, man sollte Unklarheiten vermeiden, dann spart man sich auch > das nachschauen. Naja. Bedingt. Was findest du besser lesbar?
1 | if (((a == 3) && (b == 5)) || ((x < (5 + (3 * CONST))))) { |
2 | ...
|
3 | }
|
oder
1 | if ((a == 3 && b == 5) || (x < 5 + 3 * CONST)) { |
2 | ...
|
3 | }
|
Ich finde eindeutig das Zweite besser lesbar. Dass Punktrechnung vor Strichrechnung geht, haben wir schon in der Grundschule gelernt, und alle mir bekannten Programmiersprachen halten sich dran. Dass C die Operatorenreihenfolge für logisch verkettete Vergleiche vernünftig auf die Reihe bekommen hat (anders als Pascal), kann man sich m.E. genau so gut merken, d.h. a < 5 && b > 3 funktioniert so, wie man sich das auch vorstellt (die Vergleiche binden stärkere als die logische Verknüpfung von deren Ergebnissen). Ob nun && oder || die höhere Priorität hat, ist dagegen wirklich nicht unbedingt einleuchtend und leicht zu erinnern (auch wenn es definiert ist), daher sollte man das wohl wirklich immer klammern. Gleichermaßen kann man sich m.E. auch ganz gut merken, dass es im Prinzip (*) nur noch einen Operator gibt, der weniger bindet als ?:, das ist der Komma-Operator. Alle Teilausdrücke innerhalb von ?: sind damit praktisch immer ,,fester'' gebunden, was durchaus auch dem Sinn dieses Operators entspricht. (*) Dazwischen stehen noch die kombinierten Operations- und Zuweisungsoperatoren, also += usw., die spielen hier eine eher untergordnete Rolle. Ein sehr gängiges Beispiel für die Sinnfälligkeit des ?:-Operators dürfte eine mögliche Implementierung eines MAX-Makros sein:
1 | #define MAX(a, b) ((a) > (b)? (a): (b))
|
Da es sich hier um einen Makro handelt, sollte man die expandierten Argumente jedoch immer klammern, da man ja nie weiß, was der Aufrufer darin schreibt. Das größte Problem dieses Makros ist übrigens, dass er seine Argumente zwei Mal bewertet, er hat also einen Seiteneffekt, daher per Konvention die Großschreibung.
> Was findest du besser lesbar?
Geringfügig das Zweite.
Wenn man sich stur an die Klammernschreiberei hält, dann muß man auch
nicht (erneut) nachdenken, wenn man die Zeile mal ändert.
Aber ursprünglich gings ja um den Ausdruck:
return (i+1) == MAX ? 0 : i+1;
Und da isses vorbei mit Grundschul-Punkt-vor-Strich-Wissen. Dieser
Ausdruck an sich ist schon so kompliziert, daß er IMHO aufgeteilt
werden muss!
Mehr Code würde eine Aufteilung übrigens auch nicht produzieren wie
dieser "verdichtete" C-Knäuel.
----, (QuadDash).
> Wenn man sich stur an die Klammernschreiberei hält, dann muß man > auch nicht (erneut) nachdenken, wenn man die Zeile mal ändert. Das könnte man auch gut als Argument gegen überflüssige Klammern ansehen. ;-) Wenn jemand bei einer Änderung nicht erneut über das Problem nachdenkt, begibt er sich auf einen gefährlichen Weg... Wenn die fehlenden Klammern also wirklich das Nachdenken fördern, dann sollten sie bitte schön auch weggelassen werden. :-) > Und da isses vorbei mit Grundschul-Punkt-vor-Strich-Wissen. Zusammen mit dem Wissen darum, dass ?: praktisch keine Prioriät hat: überhaupt nicht. Ich hätte das vermutlich in einen Makro ausgelagert und ihm einen Namen gegeben, der die Intention vernünftig beschreibt, aber ansonsten kann das gut die simpelste Lösung für ein bestimmtes Problem sein. Dass die Modulo-Variante keineswegs gleiche Funktionalität hat, sollte ja mittlerweile klar geworden sein.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.