Forum: PC-Programmierung [C] Komma-Operator


von Mampf F. (mampf) Benutzerseite


Lesenswert?

Grias Eich :)

beim Googeln bin ich auf das hier gestolpert:
1
int d    = 15   ; //Day     1-31
2
int m    = 5    ; //Month   1-12`
3
int y    = 2013 ; //Year    2013` 
4
5
int weekday  = (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7;

Berechnet den Wochentag aus dem Datum.

Interessant ist der Komma-Operator in der letzten Zeile ...

Ich programmier in C schon seit kA sicher 20 Jahren und eigentlich nicht 
nur trivialen Kram ... Aber den Komma-Operator hab ich vorher noch nicht 
gesehen ...

Interessanterweise kann man den Teil for den Operator nicht einfach 
hinten einsetzen, weil y verändert werden könnte. Krass Lösung ...

Google meinte, in for-Schleifen wird er oft verwendet:
1
for (a=0, b=0; a<10; a++) {
2
3
}

Also ja das kannte ich schon, aber außerhalb von for-Schleifen hab ich 
den noch nicht gesehen ...

Wer kannte den noch nicht? xD


Aber die Schaltjahr-Berechnung finde ich geil :D

VG
Mampf

: Bearbeitet durch User
von Noch einer (Gast)


Lesenswert?

Hmmm... beim International Obfuscated C Code Contest haben wir mit so 
etwas wohl keine Chance. Und wofür sollten wir es sonst benutzen?

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Noch einer schrieb:
> beim International Obfuscated C Code Contest

Soetwas gibt es? xD

von DonDiego (Gast)


Lesenswert?

Der Komma-Operator stellt ja nur die Auswertung von links nach rechts 
sicher.
In dem Beispiel will der Autor vielleicht seinen Hacker Status betonen.

von Bitwurschtler (Gast)


Lesenswert?

Mampf F. schrieb:
> Hmm, also wofür gut? ;-)

Berechnung innerhalb function calls und dort wo mensch die 
Blockanweisung {} nicht verwenden  kann, da

(expr1, expr2) quasi wie { expr1; expr2; }  funzt.

von Garcon (Gast)


Lesenswert?

https://de.m.wikibooks.org/wiki/C-Programmierung:_Ausdr%C3%BCcke_und_Operatoren

Absatz "Bedingung ?"

Manchmal ganz praktisch und kürzer aber nicht wenn es so unleserlich wie 
in dem Beispiel wird. Dann besser ausschreiben.

von Marc (Gast)


Lesenswert?

Man kann ohne Komma Operator leben.
Ich habe ihn nur dort benötigt, wo Makros was zurückliefern sollten, 
aber zusätzlich vorher noch was ausgeführt werden sollte.
Also  genau das, was man nieeemals tun sollte, es sei denn man liebt es 
sich in den Fuß zu schiessen...

von Peter D. (peda)


Lesenswert?

Mampf F. schrieb:
> Hmm, also wofür gut? ;-)

Damit d nach der Berechnung zerstört ist und man sich wundert, welcher 
Tag nun ist.
y wird auch zerstört (y--), das Komma als sequence point verhindert die 
Warnung.
Wenn Du es noch in Deinem Code durch y-1 ersetzt, ist er perfekt.

von Marc (Gast)


Lesenswert?

Peter D. schrieb:
> Wenn Du es noch in Deinem Code durch y-1 ersetzt, ist er perfekt.

Auf keinen Fall, dann wird der hintere Teil falsch gerechnet!

Tolles Beispiel für abgefahrenen Code.

Dem Entwickler würde ich anerkennend auf die Schulter klopfen,
für den Geek des Monats, und ihn schnellstens loswerden... :-)

von Marc (Gast)


Lesenswert?

Ich nehme die Entlassung zurück, nach dem Lesen des Wikipedia Artikels 
zur Wochentagsberechnug ist der Code ja 27 Jahre alt. Da durfte man noch 
so hacken...:-)

von A. S. (Gast)


Lesenswert?

Es ging damals darum, es als "Einzeiler" zu haben. Das habe ich schon 
von mehr als 27 Jahren gesehen, allerdings nicht als C-Code, damals war 
eher BASIC verbreitet (Die Zeit der Heimcomputer).

Ewige Kalender waren damals noch witzig, da es keine Handies gab. Im 
Kopf musste man die verschiedenen "Offsets" des Monats auswendig lernen. 
Für den Rechner hat dann mal jemand solange krude dividiert, bis es 
ganzzahlig zufällig passte. Der Rest ist dann einfache Mathematik. Und 
die 400-Jahre-Regel hat damals auch keinen geschert, da sie in der 
Vergangenheit nicht (bzw. nur 20 Jahre) relevant war, und in der Zukunft 
nicht vor der 10. Generation an Nachfahren.

Die Lösung hier ist halt zusammengebastelt, ohne Komma wäre sie genauso 
schwierig oder einfach.

von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

Auch gerne genommen:

return 0,1;

von Mampf F. (mampf) Benutzerseite


Lesenswert?

(º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· schrieb im Beitrag 
#5122628:
> Auch gerne genommen:
>
> return 0,1;

Für was? :)

von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

Wobei

return 1,0;

eigentlich viel besser ist um das Lesen von Quelltexten
nicht zu langweilig zu machen.


Gerne auch in Vergleichen:

if(c == 0,040){ ... }

Kommentare sollte Mann da natuerlich sparsam verwenden.

von Noch einer (Gast)


Lesenswert?

> Für was? :)

Anzahl der Programmfehler messen.

Du baust 100 Fehler absichtlich ein und zählst wie viele absichtliche 
und normale Fehler gefunden wurden. Damit kannst du dann berechnen, wie 
viele normale Fehler noch nicht gefunden wurden.

von (prx) A. K. (prx)


Lesenswert?

Ein wesentliches Motiv für die , und ?: Operatoren liegt in der 
Optimierung von Hand. Beispielsweise bei den damals wichtigen Funktionen 
getc/putc. Frühe Compiler hatten mit Inlining nichts am Hut. Die 
Effizienz der I/O wäre aber mit einem vollständigen Funktionsaufruf pro 
char beim Teufel gewesen. Also wurde die Sprache so definiert, dass man 
diese und andere kleine Funktionen ggf. auch als Präprozessor-Makros 
implementieren konnte. So wurde getc nur bei leerem Puffer zu einem 
Funktionsaufruf.

Heute sind solche Konstruktionen weitgehend obsolet.

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

Noch einer schrieb:
> Du baust 100 Fehler absichtlich ein und zählst wie viele absichtliche
> und normale Fehler gefunden wurden.

Vielen Dank! ich kannte zwar das Verfahren (mit markierten Fischen im 
Teich), aber es auf Fehler anzuwenden: Einfach genial. Egal ob SW, HW, 
Texte, Spezifikationen, ... Auch wenn die Stichprobe sicher verzerrt 
wird, da die absichtlichen Fehler eher der Art bekannter Fehler 
entsprechen (und dadurch häufiger entdeckt werden)

von Rolf M. (rmagnus)


Lesenswert?

A. K. schrieb:
> Heute sind solche Konstruktionen weitgehend obsolet.

Nicht in C++11. Denn constexpr-Funktionen dürfen dort nur ein 
return-Statement enthalten. Der komplette Funktionsinhalt muss also als 
ein einzelnes Statement geschrieben sein, das als Wert den return-Wert 
der Funktion haben muss.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Rolf M. schrieb:
> A. K. schrieb:
>> Heute sind solche Konstruktionen weitgehend obsolet.
>
> Nicht in C++11. Denn constexpr-Funktionen dürfen dort nur ein
> return-Statement enthalten.

Diese Restriktion wurde aber schon in C++14 stark gelockert, so dass man
in den Funktionen auch if-Anweisungen und nicht-statische Variablen
verwenden kann. Da sich die Aussage von A. K. auf "heute" bezieht,
trifft sie somit auch auf C++ zu.

von Oliver S. (oliverso)


Lesenswert?

Unter C++14 ist da so gut wie alles erlaubt, nicht nur if's. Lediglich 
auf Exceptions und goto muß man verzichten. Ersteres ist verständlich, 
letzteres sinnvoll.

Oliver

von Mampf F. (mampf) Benutzerseite


Lesenswert?

OMG jetzt mach ich es schon selbst und denke, das ist eine gute Idee :'(
1
switch (*p) {
2
...
3
    case 'd': note = !strncmp(p, "is", 2) ? (p+=2, 311.13) : 293.66; break;
4
...
5
}

von Thomas W. (thomas_v2)


Lesenswert?

Mampf F. schrieb:
> OMG jetzt mach ich es schon selbst und denke, das ist eine gute Idee :'(
>
>
1
> switch (*p) {
2
> ...
3
>     case 'd': note = !strncmp(p, "is", 2) ? (p+=2, 311.13) : 293.66; 
4
> break;
5
> ...
6
> }
7
>

Nenn es einfach ganz modern "Lambda-Expression", und jeder wird 
begeistert sein.

von zer0 (Gast)


Lesenswert?

Thomas W. schrieb:
> Mampf F. schrieb:
>> OMG jetzt mach ich es schon selbst und denke, das ist eine gute Idee :'(
>>
>>> switch (*p) {
>> ...
>>     case 'd': note = !strncmp(p, "is", 2) ? (p+=2, 311.13) : 293.66;
>> break;
>> ...
>> }
>>
> Nenn es einfach ganz modern "Lambda-Expression", und jeder wird
> begeistert sein.

Ich nicht. Statement-Expressions sind einfach cooler - bloß
1
case ({3;})
kompiliert nicht... Hallo!?! 3 ist konstant?!?

von Peter D. (peda)


Lesenswert?

Mampf F. schrieb:
> switch (*p) {
> ...
>     case 'd': note = !strncmp(p, "is", 2) ? (p+=2, 311.13) : 293.66;
> break;
> ...
> }

Wie kann p[0] gleichzeitig 'd' und 'i' sein?

von Vlad T. (vlad_tepesch)


Lesenswert?

Oliver S. schrieb:
> Unter C++14 ist da so gut wie alles erlaubt, nicht nur if's.
> Lediglich
> auf Exceptions und goto muß man verzichten. Ersteres ist verständlich,
> letzteres sinnvoll.
>
> Oliver

leider nicht.
Ich fänd es super, wenn man funktionen als constexpr definieren könnte, 
die tatsächlich rein von den inputs abhängen und nix weiter als ein paar 
komplizierte Berechnungen machen (aber dennoch für den selben input 
immer den selben output berechnen würden)

Leider sind selbst die grundlegendsten mathematischen Basisfunktionen 
(zB aus cmath) alle nicht als constexpr definiert.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Wie kann p[0] gleichzeitig 'd' und 'i' sein?

Danke für den Hinweis! War ungetesteter Code ... Werd ich gleich fixen 
:)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Mampf F. schrieb:
>> switch (*p) {
>> ...
>>     case 'd': note = !strncmp(p, "is", 2) ? (p+=2, 311.13) : 293.66;
>> break;
>> ...
>> }
>
> Wie kann p[0] gleichzeitig 'd' und 'i' sein?

volatile char *p;-)

Wobei das erste Argument von strncmp const char* ist und das volatile 
verloren geht; spielt aber nur eine Rolle bei hosted implementation und 
entsprechenden Optimierungen...

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Mampf F. schrieb:
> War ungetesteter Code ... Werd ich gleich fixen
> :)

Ich würds trotzdem nicht so machen. Ich hasse strcmp-Monster wo man sich 
die Strings über den Code verteilt zusammen suchen muß.
Ich schreibe lieber eine Parsefunktion, die ein Array abklappert. Das 
kann man dann schön leserlich definieren und damit leicht Schreibfehler 
oder Doppelungen erkennen.
Die Parsefunktion schreibe ich so, daß sie bei Erfolg den Pufferpointer 
hinter die geparsten Zeichen setzt. D.h. man kann sie mehrfach aufrufen, 
um zusammengesetzte Strings auszuwerten.
Muß der String in einen Wert umgewandelt werden, geht das bequem als 
Arrayindex.
1
/*
2
        compare buffer with string from list
3
        if match, return index of string
4
        list terminated by empty string
5
        advance buffer pointer to next non blank character 
6
*/
7
static uint8_t search_cmd( char *buf[], char *cmds[] )
8
{
9
  char *pbuf, *pcmd;
10
  uint8_t n;
11
  
12
  for( n = 0; *cmds[n] != '\0'; n++ ){                  // empty string = end of table
13
    pcmd = cmds[n];                                     // point to command
14
    pbuf = *buf;                                        // point to buffer
15
    for(; ((*pbuf++ ^ *pcmd++) & CASE_MASK) == 0; ){    // compare
16
      if( *pcmd == '\0' ){                              // command match
17
        *buf = skip_blanks( pbuf );                     // point to next non blank on success
18
        return n;                                       // and return command index
19
      }
20
    }
21
  }
22
  return NOT_FOUND;
23
}

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.