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.
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
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?
(tee_jotain(&luku1, &luku2);),
eiks pitäs olla tyyppimäärittely myös suluis ..vai onks tarkoituksel ny pois. -kiinnostava aihe-
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?
ja exe http://cgi.evtek.fi/~k0101030/sivut/load.php?
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.
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ä
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. :-)
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.
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.
Aihe on jo aika vanha, joten et voi enää vastata siihen.