Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: Muuttujat kasvavat kummallisesti osoittimina

Burton [04.09.2007 20:07:20]

#

Moi, olen tainnut ymmärtää jotain C:n alkeista väärin, koska kun loin tällaisen funktion:

void a(int *x, int *y) {
    .
    .
    .
    jos painetaan nappia oikealle
        *x++
    jos painetaan nappia vasemmalle
        *x--
    jos painetaan nappia alas
        *y++
    jos painetaan nappia ylös
        *y--
    .
    .
    .
}

...tuli x:n ja y:n arvoiksi aivan kummalliset tulokset. Niiden pitäisi kasvaa vain yhdellä, mutta esimerkiksi x kasvoi sadasta 10500:aan.

Mikä vika? Olen kenties käsittänyt muuttuvien muuttujien lähettämisen funktioille väärin.

hunajavohveli [04.09.2007 20:17:20]

#

Tee arvojen kasvatus ja vähennys näin:

(*x)++

Tällöin viitataan nimenomaan muuttujaan, johon x osoittaa. Alkuperäisessä koodissasi *x++ kasvatetaan osoitinta x eikä arvoa *x.

Metabolix [04.09.2007 20:17:21]

#

Ongelmasi on operaattoreiden suoritusjärjestyksessä. Koska ++ suoritetaan ennen *-operaattoria, lopputulos vastaa lausetta *(x++), toisin sanoen osoitin siirtyy yhdellä ja arvolle ei tehdä mitään. Kääntäjä varoittaakin (-Wall-lipun kanssa), että *-operaattorin tuottamaa arvoa ei käytetä missään.

Voit joko lisätä sulut, (*x)++, tai siirtyä edeltävään ++-operaattoriin, ++*x.

Blaze [04.09.2007 20:19:53]

#

*x++; ja (*x)++; on eri asioita. Ensimmäinen muuttaa paikkaa, johon pointteri osoittaa, jälkimmäinen arvoa.

Edit: ohhoh, jopas olin hidas :E

koo [05.09.2007 22:34:00]

#

Varmaan tuli jo selväksi, että ongelma johtuu siitä, että nuo operaattorit suoritetaan eri järjestyksessä kuin mitä kuviteltiin. Postfix-++ on siitä vähän hankala, että vaikka se tehdään ensiksi, sen vaikutukset näkyvät vasta lopuksi. Ehkä näitä juttuja havainnollistaa, jos kirjoitetaan pari esimerkkiä auki.

/* a = ++*x; on loogisesti sama kuin */

*x = *x + 1; /* kasvatetaan arvoa */
a = *x;

/* a = *++x; on loogisesti sama kuin */

x = x + 1; /*siirretään osoitinta eteenpäin */
a = *x;

/* a = *x++; on loogisesti sama kuin */

__tmp = x; /* vanha osoitin talteen */
x = x + 1; /* siirretään osoitinta eteenpäin */
a = *__tmp; /* arvo vanhasta paikasta */

Asiaan siis vaikuttaa operator precedence, associativity ja vähän sekin, mitä operaattorin on tarkoitus tehdä. Esimerkiksi noihin post-incrementiin ja post-decrementiin liittyy aina jonkinlainen arvon kopiointi, jonka kääntäjä voi joskus optimoida pois.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta