Moi Taas...
En viitsi aloittaa uutta topiccia niin laitan tänne vanhan jatkoksi... (Mod. huom: Aloita aina uusi, kun kysymys vaihtuu.)
Tehtävän anto on seuraava:
Tee ohjelma, joka ottaa vastaan kolme kokonaislukua ja tulostaa syötetyistä luvuista sekä pienimmän että suurimman. Pääohjelman tulee kysyä ja vastaanottaa kokonaisluvut. Laadi funktiot suurin() ja pienin(), jotka saavat parametreina syötetyt luvut. Vastaavasti funktiot palauttavat nimensä mukaiset arvot.
Vihje
Voit käyttää ohjelmassasi yhdistettyjä vertailuja ja if-else rakennetta.
Esimerkkitulostus
Anna 1. luku:1
Anna 2. luku:2
Anna 3. luku:3
Syöttämistäsi luvuista suurin oli 3 ja pienin 1.
Koodini on tämä:
#include<stdio.h> int pienin(); int suurin(); int luku1, luku2, luku3; int main(){ int a, b, c, suurempi, pienempi; printf("Anna 1. luku:"); scanf("%d", &a); printf("Anna 2. luku:"); scanf("%d", &b); printf("Anna 3. luku"); scanf("%d", &c); suurempi = suurin(a,b,c); pienempi = pienin(a,b,c); printf("Syöttämistäsi luvuista suurin oli %d ja pienin %d.", suurempi, pienempi); } int suurin(int luku1, int luku2, int luku3){ int _suurin; if(luku1 < luku2 && luku1 < luku3){ _suurin = luku1; } if(luku2 < luku1 && luku2 < luku3){ _suurin = luku2; } else{ _suurin = luku3; } } int pienin (int luku1, int luku2, int luku3){ int _pienin ; if(luku1 > luku2 && luku1 > luku3){ _pienin = luku1; } if(luku1 > luku3 && luku2 > luku3){ _pienin = luku2; } else{ _pienin = luku3; } return 0; }
saan tulokseksi isoin on 3 ja pienin on 0.
Eli onko toi isoin lukukaan oikein määritetty ?
vai onko koko hoito ihan päin peeeeetä...
Mod. lisäsi kooditagit!
No onhan toi nyt päin peetä sikäli, että esim. pienin palauttaa aina nolla. Laitat kyllä erilaisia arvoja muuttujaan _pienin, mutta et koskaan käytä ko. muuttujaa mihinkään. Suurin-funktiosta taas et palauta mitään, että mikäli toi kuitenkin kääntyy niin yhtä hyvin sieltä voisi tulla -428001 kuin 3, joka nyt hirveellä hillolla sattuu olemaan oikein.
Lähestymistavallasi on mielestäni myös jokseenkin turhaa edes tehdä mitään apumuuttujia. Jos toteat että luku1 on suurin, voisit yhtä hyvin sanoa suoraan return luku1. Lisäksi noi toimii väärin päin. Ja kannattaa huomata että else liittyy sitä edelliseen if:iin. Eli vaikka noi vertailuoperaattorit olis oikein päin ja palauttaisit apumuuttujasi, niin et saisi koskaan luku1:ä tulokseksi, kun se olisi aina luku2 tai luku3.
Yleiskommenttina sanoisin, että ohjelmoinnin ei pitäisi olla lähtökohtaisesti "yritys & erehdys" -menetelmää.
Jossei ihminen kykene ymmärtämään, kummalla puolella operaattoria '<' on suurempi ja kummalla puolella pienempi luku, niin voi unohtaa koodaamisen ihan kokonaan. Tämä on fakta.
Jos monen ehdon tekeminen peräkkäin tuntuu vaikealta, tee ensin funktio, joka vertailee kahta lukua oikein (eli tarvitset vain yhden ehdon), ja hyödynnä sitten tietoa, että suurin(a, b, c) on sama kuin suurempi(a, suurempi(b, c)).
> < merkit on väärin päin koska olen koittanut vain että mitä tapahtuu jos arvot kääntää toisinpäin...
Enkä voi väittää olevani mikään jeesus koodaamisen suhteen koska alotin ko. homman kuitenkin viikko sitten että jos tässä vaiheessa pitää olla joku guru ennen kuin tänne voi kysymyksiä laittaa niin taidan vaihtaa sit foorumia...
Olettaen ettet ole kovin paljon nuorempi kuin tuo numero nimimerkkisi perässä antaisi olettaa, niin logiikan perussäännöt saisivat jo olla hallussa. Toinen pointtini oli se, ettei tuossa pasteamassasi koodissa ole yritystä vähääkään. Tuon perusteella et ole yrittänyt ajatella minuuttiakaan. Ei tänne kannata kirjoitella kysymyksiä, joita ei ole itse pohtinut etukäteen. Vastausten laatu on suoraan verrannollinen kysymyksen laatuun.
1. Operaattorit ovat tosiaan ihan miten sattuu ja lähinnä väärin päin.
2. Toinen funktioistasi edes palauta mitään - kääntäjäsikin valittaa tästä.
Jos sinulla on vaikeuksia hahmottaa ehtolauseiden seuraamukset, niin otat kynän ja paperia ja emuloit koodia parilla eri syötteellä paperille. Jokaisen ehtolausekkeen jälkeen kirjoitat välivaiheen ylös, kunnet olet suorituksen lopussa.
siis kuka kirjottaa koodiin return 0 ja kysyy että miksi tulos on 0? :DDD lintsari
Noh kyllä ainkin tämä koulun kääntäjä menee ohjelman läpi eikä herjaa mitään virheitä... sen takia onkin vähän hankala tietää mistä etsiä vikaa...
Eka veto:
Anna 1. luku:10 Anna 2. luku:25 Anna 3. luku105 Syöttämistäsi luvuista suurin oli 105 ja pienin 0. Process returned 50 (0x32) execution time : 4.825 s Press any key to continue.
Syöttestä nähdään, että suurin luku oli 105 ja pienin oli 10. Pienimmän haku siis toimii väärin. Tutkitaan siis kyseistä funktiota. Rivi riviltä tutkittuna funktio käyttäytyy seuraavasti:
Eli täysin riipumatta syötteistä funktio palauttaa arvon nolla. Samalla tavalla kannattaa tuo suurin funktio tarkistaa ajatuksen kanssa.
Pitää testata useammilla tavoilla, esim:
1, 2, 3
3, 2, 1
2, 3, 1
1, 3, 2
Kaikkien tapauksienhan pitää toimia. Voi olla että se "hillolla" toimiva suurimman luvun etsintäkin palauttaa väärin, kun jo sanottiin että return puuttuu kokonaan.
User137 kirjoitti:
Pitää testata useammilla tavoilla, esim:
1, 1, 1
5, 5, 9
8971623, 19472386, 1239874
-13, 7, -8
Ensinnäkin SUURI KIITOS TEURO!!!
- onko esiteltävän muuttujan arvo pakko alustaa ?
Joku sentäs puhuu vielä suomeakin nyt ymmörsin jo että mikä on virheellistä kyseisessä lausekkeessa.
muutin pätkää näin.
int suurin(int luku1, int luku2, int luku3){ int _suurin ; if(luku1 > luku2 && luku1 > luku3){ _suurnn = luku1; } if(luku2 > luku1 && luku2 > luku3){ _suurin = luku2; } if(luku3 > luku1 && luku3 > luku2){ _pienin = luku3; } }
Luulin että return 0; pitää olla aina koodin lopussa...
Mod. korjasi kooditagit!
Mitä kääntäjää käytät? Jos tuo menee läpi niin sulla on asetukset väärin ja se käyttää "viimeisintä toimivaa versiota". (suurnn = luku1) Sen voit testata vaikka printtaamalla "Hello world" ohjelman alussa. Jos ei näy niin mitään mitä teet koodiin ei ole vaikutusta, eikä olis ihme ettei kääntäjä varoita.
Visual Studiossa se tapahtuu Options valikosta:
Projects and Solutions -> Build and Run:
- Project out of date -> Always build
- When deployment errors occur -> Do not launch
int suurin(int luku1, int luku2, int luku3)
Sen takia että funktiosi tyyppi on int (eikä void), niin vähintään kerran tulee return:a kutsua numeron kanssa. Missään ei sanota että juuri nolla pitää palauttaa, eikös sinun pitänyt antaa funktion tuloksena se suurin luku?
Shooter99 kirjoitti:
- onko esiteltävän muuttujan arvo pakko alustaa ?
Tähän kysymykseen sinun pitää itse löytää tai päätellä vastaus.
Shooter99 kirjoitti:
muutin pätkää näin.
– –
Luulin että return 0; pitää olla aina koodin lopussa...
Nythän tuo funktiosi ei palauta mitään, vaikka ilmoitat sen palauttavan int luvun. Mieleesi on ehkä jäänyt (virheellinen) mielikuva return lauseesta? Muutoinkin funktio on täynnä virheitä.
Sen avulla funktio palauttaa jonkun arvon. Tässä funktiossa pitäisi siis palauttaa juurikin tuo _pienin muuttujan sisältämä arvo.
Funktio saattaisi näyttää vaikkapa tällaiselta.
int pienin(int luku1, int luku2, int luku3) { if (luku1 < luku2 && luku1 < luku3) { return luku1; } else if (luku2 < luku1 && luku2 < luku3) { return luku2; } return luku3; }
Tässä on oletuksena, että kaikki luvut ovat erilaisia. Esimerkiksi syötteellä 1, 1, 3 (ja muilla vastaavilla) funktio toimii virheellisesti.
Tuosta "Nolla pitää palauttaa" hommasta tulee mieleen että joko opetuksessa on menty perse edellä puuhun tai sitten sitä ei ole ymmärretty.
Eli siis hommahan menee niin, että ohjelman pääfunktion (main) pitäisi palauttaa tieto että onnistuiko suoritus vai tapahtuiko joku virhe. On siis lähtökohtaisesti väärin ajatella, että sen pitäisi palauttaa aina 0. Se, että virhettä ei tapahtunut, ilmaistaan arvolla 0. Eli alkeita kun harjoitellaan, niin yksinkertaisuuden nimissä sinne laitetaan että se ilmoittaa aina onnistuneensa, eli return 0. Se ei kuitenkaan tarkoita edes sitä että main-funktion pitäisi aina palauttaa nolla (kuten yllä lihavoidusta käy ilmi) eikä varsinkaan että minkään muun funktion pitäisi palauttaa nolla.
Eli, jos on opetettu että pitää aina palauttaa nolla, niin on menty perse edelle puuhun. Tai jos on opetettu se mitä edellä kirjoitin, niin opetus on OK, mutta ymmärrys on ollut se copy&paste-koodarin lähestymistapa, että esimerkkikoodissa lukee return 0 -> aina pitää palauttaa 0.
Kannattaa opiskellessa muistaa, että yksinkertainen on kaunista ja varmasti myös helpompi hahmottaa.
Miksei pienimmän kolmesta luvusta palauttavaa funktiota kirjoittaisi yksinkertaisesti vain:
int pienin(int luku1, int luku2, int luku3) { int pienin = luku1; if (luku2 < pienin) pienin = luku2; if (luku3 < pienin) pienin = luku3; return pienin; }
Kun sitä sitten halutaan laajentaa toimimaan vaikka taulukolla, niin pseudokoodilla menisi vaikka näin...
int pienin(int[] luvut) { int pienin = luvut[0]; for(int i = 1; i < size(luvut); i++) { if(luvut[i] < pienin) pienin = luvut[i]; } return pienin; }
jalski kirjoitti:
Kannattaa opiskellessa muistaa, että yksinkertainen on kaunista ja varmasti myös helpompi hahmottaa.
Yksinkertaisuus on vain harvoin tehokasta.
int pienin( int luku1, int luku2, int luku3 ) { if( luku1 < luku2 ) { if( luku3 < luku1 ) return luku3; return luku1; } if( luku2 < luku3 ) return luku2; return luku3; }
Pete2 kirjoitti:
Yksinkertaisuus on vain harvoin tehokasta.
Tarkastitko kääntäjän tuottamat assembly listaukset, vai arvaatko vain?
jalski kirjoitti:
Tarkastitko kääntäjän tuottamat assembly listaukset, vai arvaatko vain?
Kuka tahansa assemblyn alkeet opetellut osaa suoraan sanoa, kuinka hidasta purkkaa funktiosi on: siihen ei tarvita mitään tarkistuksia. Kai nyt itsekin näet, että varaat muistia ja pahimmassa tapauksessa siirrät kaksi kertaa arvon muistista rekisteriin ja rekisteristä muistiin. Tämä kaikki siis täysin turhaan.
Pete2 kirjoitti:
Kuka tahansa assemblyn alkeet opetellut osaa suoraan sanoa, kuinka hidasta purkkaa funktiosi on: siihen ei tarvita mitään tarkistuksia. Kai nyt itsekin näet, että varaat muistia ja pahimmassa tapauksessa siirrät kaksi kertaa arvon muistista rekisteriin ja rekisteristä muistiin. Tämä kaikki siis täysin turhaan.
Ehkäpä kannattaisi hiukan kerrata niitä alkeita... ;-)
Eiköhän suurin osa kääntäjistä osaa käyttää rekistereitä funktion argumenttien välittämiseen. Ja vaikka tuohon käytettäisiinkin pinoa, niin käyttämäni kääntäjä ainakin kuitenkin käyttää rekisteriä tuon yhden lokaalin muuttujan tallentamiseen.
Versiosi on käyttämälläni kääntäjällä 26 tavua suurempi, eikä taida olla yhtään tehokkaampi.
0x00000000(1/1/59) ***Instruction eliminated ;Start of function pienin 0x00000000(2/1/59) push ebp 0x00000001(3/1/59) mov ebp,esp 0x00000003(4/1/59) push ebx 0x00000004(5/1/59) push esi 0x00000005(6/1/59) push edi 0x00000006(7/1/59) sub esp,=16 ;Adjusted later if temporaries allocated and maybe overwritten by subroutine call 0x0000000C(8/1/59) ***Instruction eliminated ;Register ebx contains p 0x0000000C(9/1/59) mov ecx,l3 0x0000000F(10/1/59) ***Instruction eliminated ;Register ecx contains l3 0006 int p = l1; AT F 0x0000000F(11/3/42) mov ebx,l1 0007 AT 12 0008 if (l2 < p) AT 12 0x00000012(12/4/45) cmp ebx,l2 0x00000015(13/4/45) jle Label#2 0009 p = l2; AT 1B 0x0000001B(14/4/47) mov ebx,l2 0x0000001E(15/3/49) Label Label#2 0010 if (l3 < p) AT 1E 0x0000001E(16/4/51) cmp ecx,ebx 0x00000020(17/4/51) jge Label#3 0011 p = l3; AT 26 0x00000026(18/4/53) mov ebx,ecx 0x00000028(19/3/55) Label Label#3 0012 AT 28 0013 return p; AT 28 0x00000028(20/2/57) mov eax,ebx 0x0000002A(21/2/57) ***Instruction eliminated 0x0000002A(22/1/59) Label Label#1 0x0000002A(23/1/59) lea esp,[ebp-12] 0x0000002D(24/1/59) pop edi 0x0000002E(25/1/59) pop esi 0x0000002F(26/1/59) pop ebx 0x00000030(27/1/59) pop ebp 0x00000031(28/1/59) ret
0x00000000(1/1/62) ***Instruction eliminated ;Start of function pienin 0x00000000(2/1/62) push ebp 0x00000001(3/1/62) mov ebp,esp 0x00000003(4/1/62) push ebx 0x00000004(5/1/62) push esi 0x00000005(6/1/62) push edi 0x00000006(7/1/62) sub esp,=16 ;Adjusted later if temporaries allocated and maybe overwritten by subroutine call 0x0000000C(8/1/62) mov ebx,luku3 0x0000000F(9/1/62) ***Instruction eliminated ;Register ebx contains luku3 0x0000000F(10/1/62) mov ecx,luku2 0x00000012(11/1/62) ***Instruction eliminated ;Register ecx contains luku2 0006 if( luku1 < luku2 ) AT 12 0x00000012(12/4/42) cmp ecx,luku1 0x00000015(13/4/42) jle Label#2 0007 { AT 1B 0008 if( luku3 < luku1 ) AT 1B 0x0000001B(14/6/44) cmp ebx,luku1 0x0000001E(15/6/44) jge Label#3 0009 return luku3; AT 24 0x00000024(16/6/46) mov eax,ebx 0x00000026(17/6/46) jmp Label#1 0x0000002B(18/5/48) Label Label#3 0010 return luku1; AT 2B 0x0000002B(19/4/50) mov eax,luku1 0x0000002E(20/4/50) jmp Label#1 0x00000033(21/3/52) Label Label#2 0011 } AT 33 0012 AT 33 0013 if( luku2 < luku3 ) AT 33 0x00000033(22/4/54) cmp ecx,ebx 0x00000035(23/4/54) jge Label#4 0014 return luku2; AT 3B 0x0000003B(24/4/56) mov eax,ecx 0x0000003D(25/4/56) jmp Label#1 0x00000042(26/3/58) Label Label#4 0015 AT 42 0016 return luku3; AT 42 0x00000042(27/2/60) mov eax,ebx 0x00000044(28/2/60) ***Instruction eliminated 0x00000044(29/1/62) Label Label#1 0x00000044(30/1/62) lea esp,[ebp-12] 0x00000047(31/1/62) pop edi 0x00000048(32/1/62) pop esi 0x00000049(33/1/62) pop ebx 0x0000004A(34/1/62) pop ebp 0x0000004B(35/1/62) ret
Teuro kirjoitti:
Shooter99 kirjoitti:
- onko esiteltävän muuttujan arvo pakko alustaa ?
Tähän kysymykseen sinun pitää itse löytää tai päätellä vastaus.
Olen käsittänyt että luvun voi alustaa haluttaessa jollekin luvulle mutta silti kyseinen luku ei ole kuin pienen hetken se ko. luku josta itse päättelen että alustaminen ei ole pakollista koska kuitenkin alustettu luku saa toisen arvon.
User137 kirjoitti:
Mitä kääntäjää käytät? Jos tuo menee läpi niin sulla on asetukset väärin ja se käyttää "viimeisintä toimivaa versiota".
Teemme tehtävät suoraa koulun moodle ympäristössä niin en oikeastaan tiedä edes mikä versio siellä on mutta eipä tunnu paljon herjailevan mitään...
Asensin tuon codeblocxin ja dev++:n ja koitan jos niillä saisin näitä virheitäkin esille ihan omatoimisesti.
Ja pakko myöntää että en ole mikään nopea oppimaan sekä täällä lueskellessani c kielen ohjeita niin ne joko eteni vähän turhan nopeasti minulle tai sitten vain en ymmärrä tarpeeksi basic kamaa ennen kuin alan lukemaan niitä...
Shooter99, voisitko ystävällisesti lukea keskustelun ohjeet ja käyttää viesteissäsi esim. lainaustageja ja kooditageja? Muuten viestejäsi on vaikea lukea, esim. edellisestä viestistäsi ei saanut paljonkaan selvää (ennen moderaattorin korjausta).
Selvästikään jalski ei käyttänyt kovin kummoisia optimointiasetuksia omassa testissään, kun funktioista suurin osa on täysin turhia push- ja pop-rivejä ja hyppykäskyjä.
GCC 4.7.2 -kääntäjä -O3-optimoinnilla tuottaa x86-64-koneelle tällaista:
jalski: cmpl %edi, %esi movl %edx, %eax cmovle %esi, %edi cmpl %edx, %edi cmovle %edi, %eax ret Pete2: cmpl %esi, %edi jge .L3 cmpl %edi, %edx movl %edi, %eax cmovle %edx, %eax ret .L3: cmpl %esi, %edx movl %esi, %eax cmovle %edx, %eax ret
Empiirisessä kokeessani nämä koodit ovat lähtökohtaisesti aivan yhtä nopeat, vaikka erilaisissa mutkikkaammissa tilanteissa niissä ilmeneekin satunnaisia eroja – kuten nykyään missä tahansa, kun prosessorit ovat niin outoja.
Metabolix kirjoitti:
Selvästikään jalski ei käyttänyt kovin kummoisia optimointiasetuksia omassa testissään, kun funktioista suurin osa on täysin turhia push- ja pop-rivejä ja hyppykäskyjä.
Käytössä siis Fortran kääntäjän kylkiäisenä tullut vanha C++ kääntäjä. Kääntäjä on niin vanha, että ei esimerkiksi tue nimiavaruuksia ollenkaan.
Omaan käyttööni tuo kyseinen kääntäjä tosin riittää mainiosti. Käännösaikaiset virheet C-koodissa tuo löytää kiitettävästi ja tukee myös ajonaikaista tarkistusta.
Esimerkiksi ketjun aloittajan listaus ei kääntyisi ollenkaan ja antaisi käännettäessä:
Compiling file: main.cpp C:\TEMP\MAIN.CPP(17) : error 140 - Function 'suurin' requires no arguments C:\TEMP\MAIN.CPP(18) : error 140 - Function 'pienin' requires no arguments C:\TEMP\MAIN.CPP(22) : comment 528 - Argument 'luku1' conceals a global declaration of the same symbol C:\TEMP\MAIN.CPP(22) : comment 528 - Argument 'luku2' conceals a global declaration of the same symbol C:\TEMP\MAIN.CPP(22) : comment 528 - Argument 'luku3' conceals a global declaration of the same symbol C:\TEMP\MAIN.CPP(34) : error 441 - Function 'suurin' should return a value, yet does not contain a 'return' statement C:\TEMP\MAIN.CPP(36) : comment 528 - Argument 'luku1' conceals a global declaration of the same symbol C:\TEMP\MAIN.CPP(36) : comment 528 - Argument 'luku2' conceals a global declaration of the same symbol C:\TEMP\MAIN.CPP(36) : comment 528 - Argument 'luku3' conceals a global declaration of the same symbol *** Compilation failed Compilation failed.
jalski kirjoitti:
Esimerkiksi ketjun aloittajan listaus ei kääntyisi [vanhalla C++-kääntäjällä] ollenkaan
Ei tuo käänny millään nykyaikaisellakaan C++-kääntäjällä, koska koodi ei yksinkertaisesti ole kelvollista C++-koodia vaan huonosti kirjoitettua C:tä. Itse asiassa vanhalla kääntäjällä voisi olla paremmat mahdollisuudet onnistua vahingossa kääntämään tuo.
Ensinnäkin olen pahoillani ylläpitäjälle tuottamasta lisätyöstä koska en käyttänyt lainaa tagia.
Nyt se mikä itseäni alkaa huolestuttaa on että olenko missään vaiheessa osannut koodata mitään tehtäviä oikein koska koulun c kääntäjä ajaa ohjelman läpi ja ainut virhe on ollut se että palautti pienimpänä numerona 0:n
Eli jos vanhat tehtävät on mennyt läpi ja kone on ne hyväksynyt niin miten ihmeessä tiedän olenko oikeasti koodannut mitään oikein, ja kun olen kuvitellut koodaavani ko. asiat oikein ja ottanut oppia niistä niin olen vain oppinut koko ajan koodaamaan enemmän väärin...
Kuten sanoin aiemmin, niin voit tehdä ohjelmaan jonkun pienen näkyvän muutoksen jotta tiedät onko ajettu ohjelma viimeisimmästä koodista. Muutat vaikka kyselyä:
"Anna luku: " -> "Anna joku luku: ".
Kai sieltä jotain asetuksia voi muuttaa ohjelmointiympäristöön liittyen?
Shooter99 kirjoitti:
Eli jos vanhat tehtävät on mennyt läpi ja kone on ne hyväksynyt niin miten ihmeessä tiedän olenko oikeasti koodannut mitään oikein, ja kun olen kuvitellut koodaavani ko. asiat oikein ja ottanut oppia niistä niin olen vain oppinut koko ajan koodaamaan enemmän väärin...
Asennat koneellesi C/C++-ympäristön ja testailet koodejasi sillä. Moodle on vain tarkistustyökalu toimiville vastauksille, sitä ei ole tarkoituskaan käyttää eri tapojen kokeilemiseen.
Kyllähän tuo eka koodi C-kääntäjällä menee läpi (varoituksin), mutta ei mene C++-kääntäjästä.
Hyvä tapa on että varoitukset päälle ja koodia korjataan kunnes varoituksia ei enää tule. Tosin silloinkin pitää tajuta tai ottaa selvää missä on vika, eikä räpeltää mitä sattuu.
Eka koodi antaa seuraavat varoitukset. Eikä pitäisi olla kauhean vaikeaa korjata:
gcc test1.c -o test1 -Wall test1.c: Funktio ”suurin”: test1.c:23:6: varoitus: variable ”_suurin” set but not used [-Wunused-but-set-variable] test1.c: Funktio ”pienin”: test1.c:37:6: varoitus: variable ”_pienin” set but not used [-Wunused-but-set-variable] test1.c: Funktio ”suurin”: test1.c:34:2: varoitus: ei-void-tyyppisen funktion loppu saavutettu [-Wreturn-type] test1.c: Funktio ”main”: test1.c:20:1: varoitus: ei-void-tyyppisen funktion loppu saavutettu [-Wreturn-type]
JaskaP kirjoitti:
Kyllähän tuo eka koodi C-kääntäjällä menee läpi (varoituksin), mutta ei mene C++-kääntäjästä.
Hyvä tapa on että varoitukset päälle ja koodia korjataan kunnes varoituksia ei enää tule. Tosin silloinkin pitää tajuta tai ottaa selvää missä on vika, eikä räpeltää mitä sattuu.
Eka koodi antaa seuraavat varoitukset. Eikä pitäisi olla kauhean vaikeaa korjata:
test1.c: Funktio ”suurin”: test1.c:34:2: varoitus: ei-void-tyyppisen funktion loppu saavutettu [-Wreturn-type] test1.c: Funktio ”main”: test1.c:20:1: varoitus: ei-void-tyyppisen funktion loppu saavutettu [-Wreturn-type]
Nämä varoitukset (ja läpimeno) olivat siis ns. "GNU C:llä" ja mitä tapahtui oli, että koodi menee tietystä C-kääntäjästä läpi. Sitä paitsi, esimerkiksi nykyisellä C:n määritelmällä lista olisi erilainen (jos oletetaan, että kääntäjä ei pukahtaisi muutoin kuin silloin kun standardi niin velvoittaa).
Onkohan kääntäjän pakko edes tehdä toimivaa binääriä, tai binääriä ollenkaan, kun joka tapauksessa sen ajonaikainen toiminta on määrittelemätön ("undefined")?
eq kirjoitti:
Onkohan kääntäjän pakko edes tehdä toimivaa binääriä, tai binääriä ollenkaan, kun joka tapauksessa sen ajonaikainen toiminta on määrittelemätön ("undefined")?
Clangissa on -fcatch-undefined-behavior jolla käännettynä tuo ohjelma tappaa itsensä ajon aikana ko. ongelman huomatessaan... ilmeisesti. Mutta mikään ei taida oletuksena tuollaista generoida.
Moi!
on ollut vähän kiiru viikko niin en ole päässyt käymään täällä...
No tämän koulun c kääntäjän asetuksiin emme pääse vaikuttamaan mitenkään!
Ja nyt koneellani on tollanen 79 eri c/cpp ohjelmistoa millä vääntää ja kääntää...
Ehkä vielä 10 vuoden päästä osaan oikeasti tuottaa ohjelman mikä printtaa ulos
että HELLO WORLD!
No joo, löysin netistä tuollaisen 150 sivun c kielen oppaan mitä tässä alan kahlaamaan läpi seuraavaksi.
Aihe on jo aika vanha, joten et voi enää vastata siihen.