Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: volatile unsigned char ongelmia;

Sivun loppuun

ajv [13.11.2003 15:42:44]

#

En ole C:tä kovin paljon vääntäny, mutta nyt tarttis vastauksen muutamaan kysymykseen.

1. Mihin tarkalleen ottaen käytetään 'volatile' -määritystä muuttujen esittelyn edessä. Joskus kääntäjä (borland c++) varoittaa, että "'muuttuja' is assinged a value that is never used in function main". Lisäämällä muuttujan määrittelyn eteen volatile int muuttuja = 0, edellinen varoitus häviää. Tuskin tuo on määreen käyttötarkoitus?

2.unsigned char. Mihin käytetään? Itse ongelmana on, että määrittelen kaksi muuttujaa mainissa (unsigned char luku1; unsigned char luku2;), ja tämän jälkeen yritän viedä näiden muuttujien osoitteet alifunktiolle (tee_jotain(&luku1, &luku2);), mutta alifunktiossa en kuitenkaan pysty käsittelemään kuin jälkimmäistä lukua. Lisäksi kääntäjä antaa varoituksen.

Jos joku osaa auttaa, suuret kiitokset.

DumTom [13.11.2003 17:06:37]

#

1. volatile tarkoittaa muuttujaa jota käytetään koukutetussa keskeytyksessä.
2.
signed char a voi olla -127 viiva 128
unsigned char a void olla 0 viiva 255
pelkkä char on yleensä signed eli siihen laitetaan merkki ascii taulukosta esim A=65 ja Z=90

Noista osoittimista en jaksa nyt kommentoida

vade [14.11.2003 13:25:37]

#

1. volatile kieltää kääntäjää muokkaamasta ohjelmoijan tarkoitusta kaikissa viitteissä kyseiseen muuttujaan, ts. kääntäjä ei suorita minkäänlaista näppärää optimointia tai muuta järjestelyä kyseiseen muuttujaan liittyvässä koodissa.

Esim:

volatile int n;
n = 1; // tämän kääntäjä luultavasti poistaisi, jos n ei olisi volatile
n = 2;

On tietenkin ihan kääntäjästä kiinni kuinka se käsittelee volatilet, mutta idea lienee selvä.

volatilea tarvitaan lähinnä rautaohjelmoinnissa, kun on varmistettava esim. rekisterien käytön oikea järjestys.

2. Kai tee_jotain() ottaa unsigned char -tyyppisiä osoittimia parametreina? Minkä varoituksen kääntäjä antaa?

cloudi [14.11.2003 14:07:20]

#

(tee_jotain(&luku1, &luku2);),
eiks pitäs olla tyyppimäärittely myös suluis ..vai onks tarkoituksel ny pois. -kiinnostava aihe-

ajv [14.11.2003 14:37:33]

#

lainaus:

(tee_jotain(&luku1, &luku2);),
eiks pitäs olla tyyppimäärittely myös suluis ..vai onks tarkoituksel ny pois.

Joo. tyyppimäärittelyt on suluissa, siellä missä esittelen funktion. Funktio oli esitelty: tee_jotain(int *luku1, int *luku2), ja kääntäjä valitti "Suspicious pointer conversion in function main" ja viittas riville, missä funktiota kutsutaan. Muutin funktion esittelyssä int => unsigned char niin ei enää kääntäjä valittanu, mutta edelleen tee_jotain()-funkkari ei pystynyt muuttamaan kuin jälkimmäisen pointterin takana olevaa arvoa (luku2).

No lähdekoodi on http://cgi.evtek.fi/~k0101030/sivut/load.php?filu=kotitehtava.c

ja exe http://cgi.evtek.fi/~k0101030/sivut/load.php?filu=kotitehtava.exe

Jos jotain kiinnostaa.

Kiitokset avusta. Ainakin ton volatilen käyttö aukesi.

Edit: EXE on siis toimiva versio, miten ohjelman pitäisi toimia, jonka olen joillakin poppakonsteilla saanut toimimaan oikein.

cloudi [14.11.2003 14:53:30]

#

iteki vast opiskelen näit osoittimii ja sit char-int-soppaa ,ovat kinkkisii hitsi!
oisko siis
(int *, int *);//esittely
(int *luku1, int *luku2) //funktion määritt
sitte
//kutsussa
int x,y;
tee_jotain(&x,&y);

mut mul on täs kaik ny int-tyyppisiä

vade [14.11.2003 15:56:35]

#

ajv, ongelma näyttäisi olevan kysy_luvut()-funktiossa, joka pyytää scanf()-funktiota kirjoittamaan kaksi tavua ("%i") chariin, johon yleensä, luultavasti tässäkin tapauksessa, mahtuu vain yksi tavu. Jälkimmäinen scanf-kutsu siis ylikirjoittaa l1:n osoittaman tavun (luku1) nollalla, koska luku1 ja luku2 sijaitsevat muistissa peräkkäin (kuten main()-funktiossa on määrätty), tosin yllättäen käänteisessä järjestyksessä lähdekoodiin nähden. Tästä johtuen luku1:n arvo on aina 0 kysy_luvut()-funktion palauduttua.

Muuttujien käänteinen järjestys johtuu siitä että ne on luotu funktion sisällä, eli ne ovat tallessa stackissa, joka on lifo-puskuri (last in, first out).

Koska scanf:n formaattistringi ei tunne char:n kokoista lukutyyppiä, ratkaisu on lukea luku ensin short-tyyppiseen muuttujaan (yleensä kaksi tavua), jonka lopulta kopsaat castaamalla unsigned char -tyyppiseksi:

short temp;
scanf("%i", &temp);
*l1 = (unsigned char)temp;

(Sama l2:lle.)

Toivottavasti ongelma ratkesi näinkin helposti. :-)

ajv [15.11.2003 10:04:24]

#

Kiitos vade!

Ongelma oli juuri tuo. Tosin lukujen lukeminen short-tyyppiseen muuttujaan kaatoi ohjelman. Muutin short tyypin integeriksi:

int temp;
scanf("%d", &temp);
*l1 = (unsigned char) temp;

Ja nyt toimii.

Hieman epäselväksi kuitenkin jäi miksi unsigned char -tyyppisen muuttujan muistipaikkaa ei voi lukea int-tyyppiseen pointteriin? Muistipaikan numerohan on juuri kokonaisluku.

vade [15.11.2003 12:01:29]

#

Tosiaan, %i ei välttämättä tarkoita kahta tavua, vaan se voi olla %d:n synonyymi.

No joo, asiaan.

char meaning = 42;
int *intptr = (int*)meaning;

Tätäkö tarkoitit? Tässä ei ole mitään ongelmaa. Nyt intptr osoittaa osoitteeseen 42 (0x2A). Vai tarkoititko kenties tätä:

char meaning = 42;
int *intptr = (int*)&meaning;

Nyt intptr sisältää meaning-muuttujan muistiosoitteen. Tässäkään ei ole syntaktisesti mitään väärää, mutta intptr:n kautta voit käsitellä ainoastaan int:n kokoista muistikimpaletta, joka on yleensä 4 tavua siinä missä char on yleensä 1:

*intptr = 13;

... muistiin kirjoitetaan luultavasti neljä tavua 0x0000000D (hex) vaikka meaning-muuttujaan mahtuisi vain 0x0D.


Sivun alkuun

Vastaus

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

Tietoa sivustosta