|
| Et simpel spørgsmål (primært operator prec~ Fra : Thomas Schulz |
Dato : 27-12-01 10:55 |
|
Her et noget simpel C++ taget fra
"Accelerated C++" (side 177):
size_t strlen(const char* p) {
size_t size = 0;
while (*p++ != '\0')
++size;
return size;
}
mit problem er *p++
Jeg kigger nemlig på side 120+121 fra "The C++ Programming Language -
special edition" (vist nok 3rd) af Bjarne Stroustrup.
Den siger * har mindre precedence end ++ (post)
Det vil jo sige at den først flytter "p" hen på næste element - og så
derefererer den.. Hvis det er sandt får den forkert size..
Fx 'hello\0' = er 5 chars langs, men resultatet vil blive 4.
For at overbevise sig om det kan man bare tage et kort ord, fx 'i\0' på et
bogstav.
Og så giver det jo ikke rigtigt mening. Jeg mener at left/right associativ
kun gælder i sammenhæng med andre af samme precedence?
Kan nogen forklare logikken. Hvis Bjarne har ret burde den kode fra
Accelerated C++ ikke virke (sådan som jeg forstår det).
Jeg har helt klart misforstået noget, men hvad?
Thomas
| |
Ulrik Magnusson (27-12-2001)
| Kommentar Fra : Ulrik Magnusson |
Dato : 27-12-01 11:19 |
|
Thomas Schulz wrote:
> Her et noget simpel C++ taget fra
> "Accelerated C++" (side 177):
>
> size_t strlen(const char* p) {
> size_t size = 0;
> while (*p++ != '\0')
> ++size;
> return size;
> }
>
> mit problem er *p++
>
> Jeg kigger nemlig på side 120+121 fra "The C++ Programming Language -
> special edition" (vist nok 3rd) af Bjarne Stroustrup.
>
> Den siger * har mindre precedence end ++ (post)
> Det vil jo sige at den først flytter "p" hen på næste element - og så
> derefererer den.. Hvis det er sandt får den forkert size..
Der er jo forskel på p++ og ++p - i første tilfælde vil den inkrementerede
version først dukke op næste gang p bruges.
int n = 0;
int n1 = n++; // n1 bliver 0
int n2 = ++n; // n2 bliver 2
> Fx 'hello\0' = er 5 chars langs, men resultatet vil blive 4.
> For at overbevise sig om det kan man bare tage et kort ord, fx 'i\0' på et
> bogstav.
Lad os gøre det:
strlen( 'i\0' )
size_t size = 0;
'i' != '\0' så ++size;
'\0' == '\0' så size bliver 1
Ulrik Magnusson
| |
Thomas Schulz (31-12-2001)
| Kommentar Fra : Thomas Schulz |
Dato : 31-12-01 12:55 |
|
> Der er jo forskel på p++ og ++p - i første tilfælde vil den inkrementerede
> version først dukke op næste gang p bruges.
Ville også bare lige huske at sige tak til dig.
Godt nytår alle (til dem som læser denne besked :)
mvh
Thomas Schulz
| |
Soeren Sandmann (27-12-2001)
| Kommentar Fra : Soeren Sandmann |
Dato : 27-12-01 11:26 |
|
"Thomas Schulz" <dk_sz@hotmail.com> writes:
> Det vil jo sige at den først flytter "p" hen på næste element - og så
> derefererer den.. Hvis det er sandt får den forkert size..
Det du overser, er at værdien af udtrykket p++ er p. Præcedensreglerne
betyder bare at udtrykket skal forstås som
*(p++),
ikke som
(*p)++.
Ud over at give resultatet p bevirker p++ også at p tælles op med én,
så hele udtrykket har sideeffekten at p bliver talt op med én.
| |
Bertel Lund Hansen (27-12-2001)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 27-12-01 11:51 |
|
Soeren Sandmann skrev:
>Det du overser, er at værdien af udtrykket p++ er p. Præcedensreglerne
>betyder bare at udtrykket skal forstås som
> *(p++),
Jeg har vænnet mig til at skrive den slags udtryk med paranteser,
og jeg spekulerer ikke på om de er nødvendige eller ej.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Thomas Schulz (27-12-2001)
| Kommentar Fra : Thomas Schulz |
Dato : 27-12-01 12:32 |
|
> Det du overser, er at værdien af udtrykket p++ er p. Præcedensreglerne
> betyder bare at udtrykket skal forstås som
ahhhhhhhh ja
jeg troede (tænkte på det) det som værende p+1
nu giver det hele mening
Jeg burde selv have tænkt det,
men ak,
jeg har kun tilbage at sige,
mange tak!
okay, rim og digte har aldrig lige været det som.. :)
Thomas
| |
Claus Rasmussen (27-12-2001)
| Kommentar Fra : Claus Rasmussen |
Dato : 27-12-01 19:22 |
|
Thomas Schulz wrote:
> Jeg burde selv have tænkt det,
> men ak,
> jeg har kun tilbage at sige,
> mange tak!
>
> okay, rim og digte har aldrig lige været det som.. :)
Som det første takke-rim i d.e.p.c er det nu ganske godt gået
-Claus
| |
Per Abrahamsen (28-12-2001)
| Kommentar Fra : Per Abrahamsen |
Dato : 28-12-01 15:08 |
|
Bertel Lund Hansen <nospam@lundhansen.dk> writes:
> Soeren Sandmann skrev:
>
>> *(p++),
>
> Jeg har vænnet mig til at skrive den slags udtryk med paranteser,
> og jeg spekulerer ikke på om de er nødvendige eller ej.
Jeg skriver slet ikke den slags udtryk, hverken med eller uden
parenteser.
Jeg kan generelt bedst lide hvis et udtryk enten har en sideeffekt
eller en værdi, men ikke begge ting på en gang.
| |
Ostehapsen (27-12-2001)
| Kommentar Fra : Ostehapsen |
Dato : 27-12-01 22:07 |
|
Per Abrahamsen wrote:
> Bertel Lund Hansen <nospam@lundhansen.dk> writes:
>
>
>>Soeren Sandmann skrev:
>>
>>
>>> *(p++),
>>>
>>Jeg har vænnet mig til at skrive den slags udtryk med paranteser,
>>og jeg spekulerer ikke på om de er nødvendige eller ej.
>>
Det er et spørgsmål om smag og det kan ikke diskuteres (jeg hader alle
de overflødige paranteser :) )
>
> Jeg skriver slet ikke den slags udtryk, hverken med eller uden
> parenteser.
>
> Jeg kan generelt bedst lide hvis et udtryk enten har en sideeffekt
> eller en værdi, men ikke begge ting på en gang.
Jeg studser over betegnelsen "sideeffekt". Du kan ikke lide p++? p
tælles op og værdien af udtrykket er p hvad enten du skal bruge den
eller ej, så deeet...
Hvis der er behov for performance så er det værd at overveje om der kan
være en performance-fordel i at skrive *p++ eller om behovet for "klar
kode" vejer tungere.
I forbindelse med klasser i C++ kan der være en performance-fordel i at
bruge prefix ++ (eller --) operator fremfor postfix (postfix operatoren
skrives typisk ud fra prefix operatoren).
| |
Bertel Lund Hansen (29-12-2001)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 29-12-01 00:17 |
|
Ostehapsen skrev:
>Hvis der er behov for performance så er det værd at overveje om der kan
>være en performance-fordel i at skrive *p++ eller om behovet for "klar
>kode" vejer tungere.
Det kræver et ret intimt kendskab til compileren at afgøre om det
ene er bedre end det andet - eller mange tidsstudier.
Jeg har brugt lang tid på at time forskellige operationer - på
CBM64 under Comal og Basic. Der går måneder (år?) imellem at jeg
gider nu. Den kode der er skrevet klart, sparer ofte *mange*
gange de mikrosekunder som en tweaket kode kører hurtigere. Det
gælder både 'personlige' og professionelle programmer.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Claus Rasmussen (29-12-2001)
| Kommentar Fra : Claus Rasmussen |
Dato : 29-12-01 00:45 |
|
Bertel Lund Hansen wrote:
> Ostehapsen skrev:
>
>>Hvis der er behov for performance så er det værd at overveje om der kan
>>være en performance-fordel i at skrive *p++ eller om behovet for "klar
>>kode" vejer tungere.
>
> Det kræver et ret intimt kendskab til compileren at afgøre om det
> ene er bedre end det andet - eller mange tidsstudier.
Faktisk er reglen, at man bør afholde sig fra optimeringer på det niveau.
Kompilerteknologien er i dag så udviklet, at det er meget svært at nå
bedre resultater ved at gøre det selv.
I stedet bør man vurdere, hvad der er lettest at læse. Men det er jo
temmeligt subjektivt: Jeg foretrækker konstruktioner som (*p++ = *q++)
men det er kun fordi, jeg er vant til at se dem. Andre ville foretrække
det skrevet ud i et for-loop.
-Claus
| |
Ostehapsen (28-12-2001)
| Kommentar Fra : Ostehapsen |
Dato : 28-12-01 09:39 |
|
Claus Rasmussen wrote:
> Bertel Lund Hansen wrote:
>>Det kræver et ret intimt kendskab til compileren at afgøre om det
>>ene er bedre end det andet - eller mange tidsstudier.
> Faktisk er reglen, at man bør afholde sig fra optimeringer på det niveau.
Jeg er usikker på hvad du mener med "det niveau",
men jeg tror ikke at jeg er enig :) (og jeg har aldrig hørt om den regel)
Hvis en ud af fem maskinkodeoperationer i en tæt løkke kan spares uden at
rode med maskinkode, så er det vel værd at tage med?
> Kompilerteknologien er i dag så udviklet, at det er meget svært at nå
> bedre resultater ved at gøre det selv.
Når det gælder kompilatorer til PC-programmer har du givetvis ret.
Dertil kommer at der sjældent er det store behov for optimering i
PC-programmer.
Behovet er nok større i indlejrede systemer med forholdsmæssigt
langsommere processorer og andre krav, og der findes mange obskure
kompilatorer til indlejrede systemer. Der skal nok være en eller to af
dem som ikke kan optimere nævneværdigt (og som er spækket med
underholdende fejl).
Kend dine behov, og som Bertel skriver: Kend din kompilator...
> I stedet bør man vurdere, hvad der er lettest at læse. Men det er jo
> temmeligt subjektivt: Jeg foretrækker konstruktioner som (*p++ = *q++)
> men det er kun fordi, jeg er vant til at se dem. Andre ville foretrække
> det skrevet ud i et for-loop.
Enig, ja, mange ville nok ovenikøbet foretrække at indeksere (a[t] =
b[t]) med deraf følgende performance hit (That was a good wending, maybe
we kan use that in another indlæg).
| |
Igor V. Rafienko (29-12-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 29-12-01 14:33 |
|
[ blah@blah.dk ]
[ snip ]
> Enig, ja, mange ville nok ovenikøbet foretrække at indeksere (a[t] =
> b[t]) med deraf følgende performance hit
Hvis en kompilator ikke er istand til å generere identisk kode for:
while ( *d++ = *s++ )
;
og
ssize_t i = -1;
do {
++i;
dst[i] = src[i];
} while ( dst[i] != '\0' );
så er _kompilatoren_ seriøst defekt og den _eneste_ mulige
framgangsmåten er å bytte den. Det er _ingen_ performance hit ved å
bruke op[] i forhold til op*() (forresten den første varianten bruker
en instruksjon mer på SPARC og IA32 med gcc-2.95.2. Sun Forte 6
genererer de samme instruksjonene (dog, i en annen rekkefølge)).
[ snip ]
ivr
--
Ehh... I'll have a McRudolf menu, please.
| |
N/A (30-12-2001)
| Kommentar Fra : N/A |
Dato : 30-12-01 13:50 |
|
| |
Bertel Lund Hansen (30-12-2001)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 30-12-01 13:50 |
|
Claus Rasmussen skrev:
>Jeg har også vedlagt et (linux) shell script, der måler tidsforbruget for
>de tre versioner. Når man kører det, får man flg. resultat (i 1/100s):
> Straight version : 335
> Optimized version : 343
> Extra optimized version: 341
Meget smukt eksempel.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Ostehapsen (28-12-2001)
| Kommentar Fra : Ostehapsen |
Dato : 28-12-01 09:19 |
|
Bertel Lund Hansen wrote:
> Ostehapsen skrev:
>
>
>>Hvis der er behov for performance så er det værd at overveje om der kan
>>være en performance-fordel i at skrive *p++ eller om behovet for "klar
>>kode" vejer tungere.
>>
> Den kode der er skrevet klart, sparer ofte *mange*
> gange de mikrosekunder som en tweaket kode kører hurtigere. Det
> gælder både 'personlige' og professionelle programmer.
Jeg er slet ikke uenig. Man bør kende konsekvenserne ved at foretrække
en skrivemåde fremfor en anden. Desværre (eller heldigvis?) er der delte
meninger om hvad der er tweaket hhv. klar kode.
Som regel er andres kode altid noget #¤%& hø :)
| |
Soeren Sandmann (29-12-2001)
| Kommentar Fra : Soeren Sandmann |
Dato : 29-12-01 17:34 |
|
Bertel Lund Hansen <nospam@lundhansen.dk> writes:
> gider nu. Den kode der er skrevet klart, sparer ofte *mange*
> gange de mikrosekunder som en tweaket kode kører hurtigere. Det
> gælder både 'personlige' og professionelle programmer.
Enig, og faktisk vil jeg gå længere: Den kode som er skrevet klart er
(potentielt) mange gange hurtigere end kode som er tweaket. Det hænger
sammen med at hvis man bestemmer sig for at programmet skal være
hurtigere, så er det første man skal gøre at måle hvad programmet
bruger tiden til. Hvis programmet bruger k% af tiden i en bestemt
procedure, kan optimeringer i den procedure under ingen omstændigheder
forbedre programmets hastighed med mere end k%.
Når man har målt det (ikke gættet det - man gætter næsten altid galt),
vil man have stor gavn af det hvis koden er bygget op af moduler der
ikke ved ret meget om hinandens implementationsdetaljer. Det sikrer at
optimeringer i et enkelt modul ikke indvirker på de andre. Man vil
også have gavn af at koden er skrevet læseligt, så man kan forstå hvad
der foregår og optimere uden at introducere for mange fejl.
Desuden: Hvis det endelig viser sig at en bestemt mikrooptimering er
nødvendig, er det sikkert bedre at skrive det i assembler i stedet for
at forlade sig på at compileren genererer en bestemt sekvens af
operationer. Så er man sikker på at man får de instruktioner man vil
have, og man kommer ikke til at bilde sig selv ind at det man har
foretaget sig, er portabelt.
| |
Jacob Bunk Nielsen (29-12-2001)
| Kommentar Fra : Jacob Bunk Nielsen |
Dato : 29-12-01 13:47 |
|
Ostehapsen <blah@blah.dk> writes:
>> Faktisk er reglen, at man bør afholde sig fra optimeringer på det niveau.
>
> Jeg er usikker på hvad du mener med "det niveau", men jeg tror ikke at
> jeg er enig :)
Jeg tror at Claus mener at man skal holde sig fra at spare den ene
instruktion, hvis det forringer læsbarheden af koden.
I stedet kan man så give sig til at optimere sin algoritme, det får
man ofte meget mere ud af end at optimere de enkelte sætninger i
programmet.
> (og jeg har aldrig hørt om den regel) Hvis en ud af fem
> maskinkodeoperationer i en tæt løkke kan spares uden at rode med
> maskinkode, så er det vel værd at tage med?
IMHO ikke nødvendigvis. Hvis vi taler om en løkke der skal gennemløbes
*rigtig* mange gange, og det er et reelt problem at det kører for
langsomt.
Hvis det er en løkke der skal gennemløbes et begrænset antal gange,
eller det ikke udgør et performanceproblem, så vil jeg ikke ofre det
til fordel for læsbarheden af programmet.
--
Jacob - www.bunk.cc
I used to have a drinking problem. Now I love the stuff.
| |
Per Abrahamsen (31-12-2001)
| Kommentar Fra : Per Abrahamsen |
Dato : 31-12-01 16:10 |
|
Ostehapsen <blah@blah.dk> writes:
> Jeg studser over betegnelsen "sideeffekt". Du kan ikke lide p++?
Jo, men jeg bruger ikke værdien, kun sideeffekten. Med andre ord, jeg
bruger p++ som en statement, ikke en expression.
> Hvis der er behov for performance så er det værd at overveje om der
> kan være en performance-fordel i at skrive *p++ eller om behovet for
> "klar kode" vejer tungere.
Den slags mikrooptimeringer kan compileren næsten altid klare, så der
er sjældent værd at spekulere på.
> I forbindelse med klasser i C++ kan der være en performance-fordel i
> at bruge prefix ++ (eller --) operator fremfor postfix (postfix
> operatoren skrives typisk ud fra prefix operatoren).
Jeg ved det. Det sutter. Jeg synes postfix er pænere, og bruger
alligevel ikke værdien.
| |
|
|