[C] comma operator

Pagina: 1
Acties:

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
In C heb je dus blijkbaar de comma-operator. Ik snap wel ongeveer hoe het werkt in die voorbeelden, maar nu heb ik hier een stukje code voor me in de vorm:

C:
1
h = ((a,b) && (c,d))


Wat gebeurt hier nou precies?

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 00:07

Creepy

Tactical Espionage Splatterer

De uitkomst van b en d worden gebruikt in een logische and. De uitkomst van die logische and wordt toegekend aan h.
a en c worden echter eerst geevalueerd (d.w.z. eerst a dan b, dan c en uiteindelijk d). Met de uitkomst van a en c gebeurt echter niks.

[ Voor 13% gewijzigd door Creepy op 08-09-2006 17:37 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Nvidiot
  • Registratie: Mei 2003
  • Laatst online: 11-01 23:32

Nvidiot

notepad!

Precisely stated, the meaning of the comma operator in the general expression

e1 , e2

is ``evaluate the subexpression e1, then evaluate e2; the value of the expression is the value of e2.
Oftewel:
C:
1
h = b && d

What a caterpillar calls the end, the rest of the world calls a butterfly. (Lao-Tze)


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maak daar
C:
1
2
3
a;
c;
h = b && d;

van, a en c worden namelijk wel geevalueerd, en dat maakt nogal uit als het functies zijn :)
(Bovenstaande is eigenlijk nog steeds niet correct wegens sequence points, maar dat terzijde)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Nvidiot
  • Registratie: Mei 2003
  • Laatst online: 11-01 23:32

Nvidiot

notepad!

Helemaal mee eens :)

What a caterpillar calls the end, the rest of the world calls a butterfly. (Lao-Tze)


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
Helemaal mee oneens.
C:
1
2
3
4
5
6
7
a;
if (b) {
  c;
  h = d;
} else {
  h = false;
}

Shortcut evaluatie van && niet vergeten.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-02 19:13
Dat zat ik ook net te denken, maar dat is nog niet goed als h (of d) geen bool is, maar (bijvoorbeeld) een int. (Dus op regel 4 d casten naar bool).

(Beetje mierenneuken natuurlijk, maar toch.)

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 14-02 17:55

Robtimus

me Robtimus no like you

Soultaker schreef op vrijdag 08 september 2006 @ 20:39:
Dat zat ik ook net te denken, maar dat is nog niet goed als h (of d) geen bool is, maar (bijvoorbeeld) een int. (Dus op regel 4 d casten naar bool).

(Beetje mierenneuken natuurlijk, maar toch.)
Het is C, er zijn geen bools ;)

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-02 19:13
Wat doet die 'false' in MSalters code er dan, en waar is stdbool.h voor? C'99 heeft sowieso een _Bool, en de meeste C compilers kennen ook _Bool als een extensie.

(Er zijn zoveel variaties en gebruikelijke extensies voor C, dat het niet zinnig is om je te beperken tot standaard C alleen. Er zijn bijvoorbeeld miljoenen regels C-code die // gebruiken voor commentaar, terwijl dat niet tot de oude standaard behoort.)

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 14-02 17:55

Robtimus

me Robtimus no like you

Mjah, maar zelfs dan is het in C toegestaan om booleans aan integers te assignen.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-02 19:13
Jawel (dat is het in C++ ook), maar het resultaat is verschillend.

Stel dat ik deze code uitvoer:
C++:
1
2
3
4
5
6
7
8
int a = 1, b = 2, c = 3, d = 4, h;
a; 
if (b) { 
  c; 
  h = d; 
} else { 
  h = false; 
}

Dan is h uiteindelijk 4! Dat is anders dan de oorspronkelijke code:
C++:
1
h = ((a,b) && (c,d))

Nu is h namelijk 1.

MSalters' code is niet correct, zonder d naar bool te casten, of extra informatie over de typen van de expressies te geven. Het enige wat je kunt aannemen is dat de oorspronkelijke expressie geldig was, en dan is die cast essentieel.

[ Voor 10% gewijzigd door Soultaker op 08-09-2006 21:32 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
Mja begrijp wel wat er gebeurt, maar in de volgende situatie raak ik dan toch weer de weg kwijt. Het betreft een functie uit de PrBoom (DOOM port) sourcecode:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Hash function used for lump names.
// Must be mod'ed with table size.
// Can be used for any 8-character names.
// by Lee Killough

unsigned W_LumpNameHash(const char *s)
{
  unsigned hash;
  (void) ((hash =        toupper(s[0]), s[1]) &&
          (hash = hash*3+toupper(s[1]), s[2]) &&
          (hash = hash*2+toupper(s[2]), s[3]) &&
          (hash = hash*2+toupper(s[3]), s[4]) &&
          (hash = hash*2+toupper(s[4]), s[5]) &&
          (hash = hash*2+toupper(s[5]), s[6]) &&
          (hash = hash*2+toupper(s[6]),
           hash = hash*2+toupper(s[7]))
         );
  return hash;
}


Hoe zou je dat nou kunnen opschrijven zonder die vreemde comma operator? Ik probeer te doorzien hoe de hash wordt berekend maar ik snap het gewoon niet...:(

[ Voor 7% gewijzigd door Genoil op 09-09-2006 09:42 ]


  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

OK, stap voor stap. De expressie om de hash te berekenen is een verzameling termen (elk van de vorm (e1, e2)) die met conjuncties aan elkaar geplakt is en waarbij e1 steeds als side-effect heeft dat de waarde van de variabele hash verandert, terwijl e2 ervoor zorgt dat de evaluatie van de hele uitdrukking kortgesloten wordt als ergens in de string (die uit 8 echte karakters moet bestaan) een NULL-teken voorkomt. Een equivalente notatie (voor de duidelijkheid met expliciete tests op '\0') zou dus zijn:

C:
1
2
3
4
5
6
7
8
9
    hash = toupper(s[0]);

    if (s[1] != '\0') { hash = (hash * 3) + toupper(s[1]);
        if (s[2] != '\0') { hash = (hash * 2) + toupper(s[2]);
            if (s[3] != '\0') { hash = (hash * 2) + toupper(s[3]);
                if (s[4] != '\0') { hash = (hash * 2) + toupper(s[4]);
                    if (s[5] != '\0') { hash = (hash * 2) + toupper(s[5]);
                        if (s[6] != '\0') { hash = (hash * 2) + toupper(s[6]);
                            if (hash = (hash * 2 + toupper(s[7]))); }}}}}}


Verder is er niets mysterieus aan die operator, je gebruikt het ding alleen zovaak onbewust dat -ie wat vreemd oogt in dit soort extreme gevallen. ;)

[ Voor 4% gewijzigd door DroogKloot op 09-09-2006 21:49 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:54
Het spijt me zeer maar is dit nou een beetje flexen met code oid? Wat schiet je er mee op dat men een half uur moet studeren op 8 regels code om te begrijpen wat er staat?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een simpel forlusje had idd een stuk beter geweest.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-02 19:13
Een beetje C-programmeur leest dit zo weg, hoor. Het is ook niet echt obfuscated, en uit de context wordt wel duidelijk wat er ongeveer gaat gebeuren (een hash-code berekenen voor een zero-terminated string).

Maar inderdaad, een for-lusje was mooier geweest, zeker aangezien loop unrolling hier weinig nut heeft aangezien je na elke update van de hashcode toch een conditionele jump moet doen (wat normaalgesproken juist niet zo is).

Het is bovendien een vrij slechte hash functie, maar dat terzijde.

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
Nouja inderdaad, het was me wel duidelijk wat er moerst gebeuren in die functie, maar ik vond het maar een beetje raar opgeschreven dat ik er een beetje achterdochtig van werd :). Ik zie nu dat er idd niet zo heel veel spannends gebeurd :).

Wat betekent trouwens 'flexen met code'? Ik ken geen turbo-taal :P (en ook nauwelijks C ;))

[ Voor 26% gewijzigd door Genoil op 10-09-2006 10:16 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:54
Soultaker schreef op zondag 10 september 2006 @ 01:34:
Een beetje C-programmeur leest dit zo weg, hoor.
Voel me best op mijn gemak als ik met C werk maar misschien ben ik dan gewoon nog een complete C n00b :) . Ik moet echt te lang kijken naar mijn gevoel om te begrijpen wat er staat.
Wat betekent trouwens 'flexen met code'?
Nou ja, je weet wel ... flexen doet iemand in de sportschool met zijn biceps ... flexen met code is de nerd vorm daarvan :)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
farlane schreef op zondag 10 september 2006 @ 16:11:
[...]
Voel me best op mijn gemak als ik met C werk maar misschien ben ik dan gewoon nog een complete C n00b :) . Ik moet echt te lang kijken naar mijn gevoel om te begrijpen wat er staat.
[...]
Nou ja, je weet wel ... flexen doet iemand in de sportschool met zijn biceps ... flexen met code is de nerd vorm daarvan :)
Aha dus je had een beetje hetzelfde idee bij die code als ik...maar of het nou 'flexen' is weet ik niet, een loopje is er ook niet zo eenvoudig van gemaakt (er staat 1 keer hash * 3 ipv hash * 2 enzo), maarja ik geloof dat bij een hash de uitkomst van een bepaalde berekening niet het belangrijkste is...

Ik ben natuurlijk niet voor niets aan het uitvissen hoe er in DOOM met WAD files gewerkt word, dus tzt kan ik nog wel even proberen of ik dat hashalgoritme ook wat minder vaag kan opschrijven...

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 14-02 19:13
Met een lusje kan 'ie zo:
C:
1
2
3
4
5
6
7
unsigned W_LumpNameHash(const char *s) 
{ 
    static unsigned tab[] = { 1, 3, 2, 2, 2, 2, 2, 2, 0 };
    unsigned hash = 0, *m = tab;
    while(*s && *m) hash =  *m++ * hash + toupper(*s++);
    return hash;
}

Waarschijnlijk minder efficient, en nauwelijks duidelijker. Het is gewoon een rare ad-hoc hashcode, om de eerste 8 bytes van een string te hashen. Ik zou 'm gewoon lekker laten staan als 'ie is.

[ Voor 12% gewijzigd door Soultaker op 10-09-2006 17:22 . Reden: Valt nog niet mee =) ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Idd niet duidelijker, deze wel imho:
C:
1
2
3
4
5
6
7
8
9
10
11
12
unsigned W_LumpNameHash(const char *s)
{
    unsigned hash = toupper(s[0]), mul = 3, i;
    if (!hash)
        return 0;
    for (i = 1; i < 8 && s[i]; i++)
    {
        hash = hash * mul + toupper(s[i]);
        mul = 2;
    }
    return hash;
}


Reden: geen vage pointers die de stopcondities bepalen - je ziet duidelijk dat ie op de eerste 8 chars van de string werkt.

[ Voor 23% gewijzigd door .oisyn op 11-09-2006 11:48 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
.oisyn schreef op maandag 11 september 2006 @ 11:44:
Idd niet duidelijker, deze wel imho:
C:
1
2
3
4
5
6
7
8
9
10
11
12
unsigned W_LumpNameHash(const char *s)
{
    unsigned hash = toupper(s[0]), mul = 3, i;
    if (!hash)
        return 0;
    for (i = 1; i < 8 && s[i]; i++)
    {
        hash = hash * mul + toupper(s[i]);
        mul = 2;
    }
    return hash;
}


Reden: geen vage pointers die de stopcondities bepalen - je ziet duidelijk dat ie op de eerste 8 chars van de string werkt.
Ja dit is idd veel leesbaarder!

(de originele code is dan ook niet van meneer Carmack himself, maar slechts van een 'porter')

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13-02 18:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Alsof Carmack van die mooie code schrijft ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
.oisyn schreef op maandag 11 september 2006 @ 14:57:
Alsof Carmack van die mooie code schrijft ;)
oh is dat zo? ik heb er eigenlijk nooit naar gekeken...kzal eens kijken of er veel verschil zit tussen de prboom source en de echte doom source. Viel me wel op dat er van de Quake source versies in omloop zijn die 'cleansrc' heten...da's ook vast niet voor niets ;)
Pagina: 1