[C] Komma-Operator

OP Persönliche Seite #5122348
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
Gast #5122388
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...
Gast #5122407
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... :-)
Gast #5122468
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.
Gast #5122732
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.
Gast #5122815
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.
#5122826
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.
Gast #5122878
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)
Moderator #5123077
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.
Gast #5127825
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?!?
#5128103
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.
Persönliche Seite #5128511
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...
#5128544
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren