Enkla men fatala buggar
Re: Enkla men fatala buggar
När skillnad i precedens saknas skall det evalueras från vänster till höger.
Det svåra är väl att tänka igenom uttrycken och att en del kompilatorer inte följer standard. En genväg är då att använda explicita paranteser för att tvinga igenom precedens. Men det kan bli många paranteser..
Det svåra är väl att tänka igenom uttrycken och att en del kompilatorer inte följer standard. En genväg är då att använda explicita paranteser för att tvinga igenom precedens. Men det kan bli många paranteser..
Re: Enkla men fatala buggar
Nja, det finns inget krav i C-standarden om det, vill jag minnas, utan är plattforms/kompilator beroende.
F kan evalueras före g eller viceversa, så om då en av funktionerna påverkar variabler som används i den andra, kan vad som helst hända.
Samma gäller till exempel:
Ovanstående två exempel ger vilt skilda resultat beroende på kompilatorn, och kan faktiskt ge olika resultat mpå samma kompilator, vid två påföljande kompileringar.
Ta till exempelK&R skrev:The moral is that writing code that depends on order of evaluation is bad programming practice in any language
Kod: Markera allt
X = f() + g();
Samma gäller till exempel:
Kod: Markera allt
printf ( "%d %D\n", ++n, power(2,n));
a[i] = i++;
Re: Enkla men fatala buggar
Följer man inte goda råd så kan vad som helst hända.... t.ex. att man struntar i att använda parenteser.blueint skrev:Följer program inte specifikationer så kan vad som helst hända..
Re: Enkla men fatala buggar
C89, C90, C99, C11 osv. Man kan förstås välja att inte följa dessa. Men då får skaparen av kompilatorn vara tydlig med detta.
Re: Enkla men fatala buggar
Oavsett om man följer standarden eller inte så är det dålig programmering att inte vara tydlig i vad som görs. Så kör man utan parenteser anser jag att koden är ofullständig och dålig.
Re: Enkla men fatala buggar
Står det "unspecified" eller "undefined" så kör man stenhårt med paranteser. Kanske man t.om slänger in en enkel funktion som kontrollerar att kompilatorn gör rätt.
Re: Enkla men fatala buggar
I de fallen jag kommer att tänka på där det är odefinierat (som i TomasLs exempel) så hjälper det inte med parenteser. Men det kanske finns sådana fall också?
Re: Enkla men fatala buggar
Om det inte hjälper att t.ex göra om:
Till:printf ( "%d %D\n", ++n, power(2,n));
Eller t.om:n++;
printf ( "%d %D\n", n, power(2,n));
Samt "low = input & 0x0F << 4" till "low = (input & 0x0F) << 4" då är det illa!n++;
pw = power(2,n);
printf ( "%d %D\n", n, pw);
Re: Enkla men fatala buggar
De exemplen jag visade måste delas upp så att man använder mellanresultat, för att få korrekt funktion på det hela och i den oordningen man vill ha det.
Generellt gäller dock alltid parenteser och ofta mellanresultat (vilka naturligtvis är enklare att debugga).
Generellt gäller dock alltid parenteser och ofta mellanresultat (vilka naturligtvis är enklare att debugga).
Re: Enkla men fatala buggar
blueint:
Självklart skall det skrivas om, men kanske inte på det sätt du föreslår.
Det beror på om programmeraren vill använda det 'gamla' eller 'nya' värdet på 'n' vid anrop av power().
Och det vet bara denne (förhoppningsvis). Och eftersom det saknas kommentarer så kan ingen veta hur det skall vara.
Det enda vi kan säga är att resultatet inte är entydigt.
Vid funktionsanrop kan argumenten beräknas i valfri ordning (kompilatorberoende) enligt standard.
Just därför kan/skall man inte både beräkna och använda en variabel flera gånger i ett funktionsanrop.
Kod: Markera allt
printf ( "%d %D\n", ++n, power(2,n));
Det beror på om programmeraren vill använda det 'gamla' eller 'nya' värdet på 'n' vid anrop av power().
Och det vet bara denne (förhoppningsvis). Och eftersom det saknas kommentarer så kan ingen veta hur det skall vara.
Det enda vi kan säga är att resultatet inte är entydigt.
Vid funktionsanrop kan argumenten beräknas i valfri ordning (kompilatorberoende) enligt standard.
Just därför kan/skall man inte både beräkna och använda en variabel flera gånger i ett funktionsanrop.
Re: Enkla men fatala buggar
T.ex. kan man skriva:TomasL skrev: Ta till exempelF kan evalueras före g eller viceversa, så om då en av funktionerna påverkar variabler som används i den andra, kan vad som helst hända.Kod: Markera allt
X = f() + g();
Kod: Markera allt
float X, f_del, g_del; /* xxx-funktionernas summa samt del-resultat */
...
/* Beräkna delresultaten från ggg och fff. OBS! g() måste beräknas först eftersom vissa globala variabler påverkas som f() behöver */
g_del=g():
f_del=f();
X=f_del+g_del; /* Summan av ggg och fff är klar. Även de globala variablerna har uppdaterats */
Förhoppningsvis är kodsnutten tolkningsbar för näste programmerare om 18 månader.
Dessutom ger den förhoppningsvis samma resultat även om kompilator ändras eller byts till annat fabrikat.