Miksi kouluissa/opistoissa

A Aimo

tahkotaan edelleen C-kieltä?
Kun C kielellä voi tehdä täysin samat hommat kuin pelkällä ceellä.
Cee plus plussalla taasen voi tehdä sellaista mitä ceellä ei voi.
Mikä järki tuossa koulutuksessa on?

16

1397

    Vastaukset 16

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • Ensiksikin, C-kieli on yksinkertaisempi ja helpompi oppia kuin C eikä sen kanssa ole oppimiskynnys jyrkkä kun ei tarvitse ymmärtää olio-ohjelmoinnista mitään.

      Toisekseen, C-kielellä on sellainen vahvuus, että sillä toteutettuja komponentteja voi käyttää vaivatta eri useissa muissa ohjelmointikielissä ja siksi C-kieli on alan standardi yleiskäyttöisissä kirjastoissa. Lisäksi C-kieli kun on yksinkertaisempi, se tarvitsee vähemmän massaa tukikirjastoon ja saa sitten käännettyä jonkin verran kevyempiä ohjelmia. Tällä on merkitystä kevyemmissä laitteissa.

      • C- kieli on muinaisjäänne

        Ihminen, joka aloittaa ensimmäistä kertaa elämässään jonkun ohjelmointikielen opiskelun, oli kyseessä sitten C tai C niin molemmat kielet ovat yhtä vaikeita/helppoja.

        Kiinassa lapset oppivat puhumaan ja kirjoittamaan Kiinaa ihan yhtä vanhoina kuin suomalaiset lapset oppivat puhumaan ja kirjoittamaan suomea. Vaikka joku väittäisikin, että kiinankieli on paljon paljon vaikeampaa.


      • C- kieli on muinaisjäänne kirjoitti:

        Ihminen, joka aloittaa ensimmäistä kertaa elämässään jonkun ohjelmointikielen opiskelun, oli kyseessä sitten C tai C niin molemmat kielet ovat yhtä vaikeita/helppoja.

        Kiinassa lapset oppivat puhumaan ja kirjoittamaan Kiinaa ihan yhtä vanhoina kuin suomalaiset lapset oppivat puhumaan ja kirjoittamaan suomea. Vaikka joku väittäisikin, että kiinankieli on paljon paljon vaikeampaa.

        "Ihminen, joka aloittaa ensimmäistä kertaa elämässään jonkun ohjelmointikielen opiskelun, oli kyseessä sitten C tai C niin molemmat kielet ovat yhtä vaikeita/helppoja."

        Olioparadigmassa on ylimääräistä oppimista, lisäksi C on astetta monimutkaisempi ja siinä on enemmän oppimista että sen hallitsee.


      • yo:laisille
        M-Kar kirjoitti:

        "Ihminen, joka aloittaa ensimmäistä kertaa elämässään jonkun ohjelmointikielen opiskelun, oli kyseessä sitten C tai C niin molemmat kielet ovat yhtä vaikeita/helppoja."

        Olioparadigmassa on ylimääräistä oppimista, lisäksi C on astetta monimutkaisempi ja siinä on enemmän oppimista että sen hallitsee.

        "Olioparadigmassa on ylimääräistä oppimista, lisäksi C on astetta monimutkaisempi ja siinä on enemmän oppimista että sen hallitsee."

        Tästä vastustuksesta huolimatta yliopistoissa koodauksen opettelu aloitetaan (monien kohdalla nollasta) Javalla, joka on jopa C :aa puhtaampi oliokieli.


    • 0000000000000000

      Ehkä sen takia ettei mene tumput suuhun sitten kun pitää kirjoittaa tai suunnitella C -kielisiä ohjelmia tai kirjastoja. Laitteistoläheinen koodi on usein kirjoitettu C:llä ja sulautettujen puolella ei aina edes ole saatavilla C kääntäjää. Lukuisat kirjastot ovat kirjoitettu myös C:llä ilman luokka ajattelua.

      Toisaalta voidaan kysyä mitä järkeä on opetella C :aa eikä esim. C:tä ja Pythonia, C:tä ja Javaa tai C:tä ja C#:ia. Yksi syy C:n opiskeluun on se mitä yhdessä viestissä sanottiin, eli kun opiskelijoille haluaan opettaa perusteita (for, while, do while, jne, muttujat, jne.) ei silloin kannata sotkea mukaan olio käsitteitä.

    • Tahvo Tohveli

      Miksi hankkia koira, kun voi hankkia mustekalan, joka on tehty naulaamalla neljä lautaa koiraan? Se voi tehdä kaiken mitä tavallinen koira voi tehdä, ja lisäksi se on mustekala.

    • Paremmat

      Kunnon opinahjoissa opetetaan paljon parempia kieliä, niin korkeamman tason käsitteet tulevat tutuiksi alusta alkaen. Siitä on ihan tutkittuja tuloksia: C -kielellä aloittavat opiskelijat pärjäävät keskimäärin huonommin jatkokursseilla, kuin erityisesti opetukseen hyvin sopivilla kielillä aloittaneet.

      C ja C voidaan opetella tarpeen mukaan.

    • pitäisi aloittaa

      assemblerilla niin perusasiat kuten muistin rakenne, tavukoodi yms tulee tutuksi

      • Kieltämättä joo. Ihmiset jotka ei lähde opiskelemaan alhaalta ylöspäin, eivät oikeastaan ymmärrä asioista yhtään mitään. Tavukoodilla ei kyllä ole oikeastaan mitään merkitystä mutta CPU:n toiminta yms. pitäisi kyllä olla selvillä.


      • TRRY

        Assemblyllä ohjelmoimalla *ei* tule tavukoodi tutuksi. Jälkimmäinen on ohjelmointikielen tulkin (jota joskus myös virtuaalikoneeksi kutsutaan) käyttämä välikieli, missä perinteisesti yhden käskyn pituus on yksi tavu (tästä tulee myös nimi "tavukoodi"). Tavukoodia suoritetaan hyvin usein pinokoneella, kuten esim. JavaVM ja Python tekevät. Tavukoodin suorittaminen on huomattavasti nopeampaa kuin koodin suora tulkkaaminen.

        Assemblyssä eli symbolisessa konekielessä käännös puolestaan tehdään konekielelle. Konekielisen käskyn pituus riippuu prosessoriarkkitehtuurista, ja joissakin arkkitehtuureissa myös käskystä itsestään. x86:ssakin jotkin käskyt ovat pidempiä kuin toiset.

        Assemblyllä ohjelmoidessa joutuu tuskailemaan monien prosessoriarkkitehtuurista johtuvien ikävyyksien kanssa: esimerkiksi rekisterien määrä ja koko vaihtelevat paljon. Kun rekistereitä on vähän (kuten x86:ssa), niin tylsä osuus kasvaa: tarpeettoman tuntuisia muistihakuja ja -tallennuksia saa tehdä usein. Jos välttämättä haluaa opetella ohjelmoimaan tästä näkökulmasta, olennaiseen voi keskittyä vähemmällä tuskalla ottamalla alustaksi jonkin hieman teoreettisemman Register_machine:n (ks. wikipediaa) kuin oikean prosessoriarkkitehtuurin.

        C on "portattava assembly". Silläkin ohjelmoidessa pääsee ihan riittävästi (ja välillä vähän liiankin läheltä mm. "bus erroreiden" kautta) kiinni mm. muistin rakenteeseen. C puolestaan tarjoaa mahdollisuuden päästä eroon osoittimista, muttei kuitenkaan pakota siihen.


      • TRRY kirjoitti:

        Assemblyllä ohjelmoimalla *ei* tule tavukoodi tutuksi. Jälkimmäinen on ohjelmointikielen tulkin (jota joskus myös virtuaalikoneeksi kutsutaan) käyttämä välikieli, missä perinteisesti yhden käskyn pituus on yksi tavu (tästä tulee myös nimi "tavukoodi"). Tavukoodia suoritetaan hyvin usein pinokoneella, kuten esim. JavaVM ja Python tekevät. Tavukoodin suorittaminen on huomattavasti nopeampaa kuin koodin suora tulkkaaminen.

        Assemblyssä eli symbolisessa konekielessä käännös puolestaan tehdään konekielelle. Konekielisen käskyn pituus riippuu prosessoriarkkitehtuurista, ja joissakin arkkitehtuureissa myös käskystä itsestään. x86:ssakin jotkin käskyt ovat pidempiä kuin toiset.

        Assemblyllä ohjelmoidessa joutuu tuskailemaan monien prosessoriarkkitehtuurista johtuvien ikävyyksien kanssa: esimerkiksi rekisterien määrä ja koko vaihtelevat paljon. Kun rekistereitä on vähän (kuten x86:ssa), niin tylsä osuus kasvaa: tarpeettoman tuntuisia muistihakuja ja -tallennuksia saa tehdä usein. Jos välttämättä haluaa opetella ohjelmoimaan tästä näkökulmasta, olennaiseen voi keskittyä vähemmällä tuskalla ottamalla alustaksi jonkin hieman teoreettisemman Register_machine:n (ks. wikipediaa) kuin oikean prosessoriarkkitehtuurin.

        C on "portattava assembly". Silläkin ohjelmoidessa pääsee ihan riittävästi (ja välillä vähän liiankin läheltä mm. "bus erroreiden" kautta) kiinni mm. muistin rakenteeseen. C puolestaan tarjoaa mahdollisuuden päästä eroon osoittimista, muttei kuitenkaan pakota siihen.

        "Assemblyllä ohjelmoimalla *ei* tule tavukoodi tutuksi."

        Konekieli on tavukoodia.. Sitä vaan ajaa prosessori eikä virtuaalikone.


      • TRRY
        M-Kar kirjoitti:

        "Assemblyllä ohjelmoimalla *ei* tule tavukoodi tutuksi."

        Konekieli on tavukoodia.. Sitä vaan ajaa prosessori eikä virtuaalikone.

        Konekieli on tavukoodia yhtä paljon kuin C on Smalltalkia. Niillä ohjelmoiva huomaa eroaja suoritusalustojen lisäksi komennoissa, kirjastoissa, suoritusnopeuksissa, käyttötarkoituksissa ja joustavuudessa. Siksi niitä ei pidä sekoittaa keskenään.


      • TRRY kirjoitti:

        Konekieli on tavukoodia yhtä paljon kuin C on Smalltalkia. Niillä ohjelmoiva huomaa eroaja suoritusalustojen lisäksi komennoissa, kirjastoissa, suoritusnopeuksissa, käyttötarkoituksissa ja joustavuudessa. Siksi niitä ei pidä sekoittaa keskenään.

        Hölöpönpölöpön. Tavukoodia on monenlaista ja niitä voi ajaa niin virtuaalikoneella kuin raudalla. Olen ajanut esim. x86 -koodia softalla ja raudalla, kuten olen myös ajanut 6502:n koodia. Javaa olen ajanut vain softalla, mutta kyllähän sitä Javaprosessoreitakin löytyy. Ettei vaan olisi kännyköiden ARM -vehkeissä tukea suoraan Javan tavukoodille..

        Niin ja minä sitten osaan muutaman prosessorin konekielen, että kyllä niissä eri arkkitehtuurien tavukoodeissa on kummasti eroja.


      • TRRY
        M-Kar kirjoitti:

        Hölöpönpölöpön. Tavukoodia on monenlaista ja niitä voi ajaa niin virtuaalikoneella kuin raudalla. Olen ajanut esim. x86 -koodia softalla ja raudalla, kuten olen myös ajanut 6502:n koodia. Javaa olen ajanut vain softalla, mutta kyllähän sitä Javaprosessoreitakin löytyy. Ettei vaan olisi kännyköiden ARM -vehkeissä tukea suoraan Javan tavukoodille..

        Niin ja minä sitten osaan muutaman prosessorin konekielen, että kyllä niissä eri arkkitehtuurien tavukoodeissa on kummasti eroja.

        > Tavukoodia on monenlaista ja niitä voi ajaa
        > niin virtuaalikoneella kuin raudalla.

        Päin honkia. Pelkään sinun sekoittavan tavukoodin ja konekielen lisäksi vielä virtuaalikoneetkin pahan kerran. Koitetaan nyt pitää erillään tavukoodia suorittavat virtuaalikoneet (esim. JavaVM ja Python-tulkki) ja joitakin rautaa emuloivat ja tietyn prosessoriarkkitehtuurin konekieltä suorittavat virtuaalikoneet (esim. Qemu, UAE, Vice). Jälkimmäisillä ei ole sen enempää tekemistä tavukoodin kanssa kuin 80386-, 68000- tai 6510-prosessoreillakaan.

        Yritän selvittää tavukoodin ja konekielen eron vielä yhden kerran. Tavukoodi on suunniteltu ajettaviksi softalla. Siksi siinä voidaan käyttää ja käytetään sellaisia käskyjä, joita ei voi toteuttaa suoraan millään järkevällä raudalla. Syy on siinä, ettei monestakaan syystä ole järkevää tehdä rautaa, joka suoriutuisi sellaisista käskyistä. Otetaan yksinkertainen esimerkki: kertolasku.

        Kopioi Python-tulkkiin seuraavat rivit:

        import dis # tavukoodin disassembler
        dis.dis(lambda x,y: x*y) # (1)
        dis.dis(lambda x,y: [x]*y) # (2)

        Rivi (1) tulostaa tavukoodin funktiosta, joka kertoo kaksi parametrina saamaansa alkiota. Rivi (2) tulostaa tavukoodin funktiosta, joka tekee ensimmäisestä parametrista yhden alkion pituisen listan ja kertoo listan toisella parametrilla. (Pythonissa listan kertominen luvulla n tuottaa uuden listan, joka on vanha lista toistettuna n kertaa peräkkäin.)

        Vertaa sitten edellisten tavukoodien kertolaskun suorittavaa käskyä C-kääntäjän tuottamaan assemblyyn (valitse mieleisesi prosessoriarkkitehtuuri).

        Kertolasku kokonaisluvuilla:

        echo "int kerro(int x, int y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...pienillä kokonaisluvuilla...

        echo "char kerro(char x, char y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...isoilla kokonaisluvuilla...

        echo "long long kerro(long long x, long long y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...liukuluvuilla...

        echo "float kerro(float x, float y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...ja hieman tarkemmilla liukuluvuilla...

        echo "double kerro(double x, double y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        Luultavasti näit aika monta eri käskyä pelkän kertolaskun suorittamiseen, ellet kääntänyt koodia 6502:lle. :)

        Mutta nuokaan käskyt eivät vielä suoriudu esim. listan monistamisesta. Kuitenkin kummallekin Python-funktiolle kävisi ensimmäiseksi parametriksi pienet luvut, isot luvut, liukuluvut, rajattoman tarkkuuden kokonaisluvut, listat ja merkkijonot ja monen muun tyyppiset arvot. Sama tavukoodi ja erityisesti sama kertolaskukäsky toimii silti.

        Toivottavasti tämä auttaa ymmärtämään eron tavukoodin ja konekielen välillä. Ne on suunniteltu hyvin erilaisiin tarkoituksiin. Konekielen suoritusta on vielä kohtuullisen helppoa simuloida softalla, mutta tavukoodiapa ei ajetakaan raudalla ihan helposti. Yhden ainoan tavukoodin käskyn suorittaminen saattaa kestää tunteja, vaikka prosessorissa gigahertsejä riittäisi jokaiselle sormelle.


      • TRRY kirjoitti:

        > Tavukoodia on monenlaista ja niitä voi ajaa
        > niin virtuaalikoneella kuin raudalla.

        Päin honkia. Pelkään sinun sekoittavan tavukoodin ja konekielen lisäksi vielä virtuaalikoneetkin pahan kerran. Koitetaan nyt pitää erillään tavukoodia suorittavat virtuaalikoneet (esim. JavaVM ja Python-tulkki) ja joitakin rautaa emuloivat ja tietyn prosessoriarkkitehtuurin konekieltä suorittavat virtuaalikoneet (esim. Qemu, UAE, Vice). Jälkimmäisillä ei ole sen enempää tekemistä tavukoodin kanssa kuin 80386-, 68000- tai 6510-prosessoreillakaan.

        Yritän selvittää tavukoodin ja konekielen eron vielä yhden kerran. Tavukoodi on suunniteltu ajettaviksi softalla. Siksi siinä voidaan käyttää ja käytetään sellaisia käskyjä, joita ei voi toteuttaa suoraan millään järkevällä raudalla. Syy on siinä, ettei monestakaan syystä ole järkevää tehdä rautaa, joka suoriutuisi sellaisista käskyistä. Otetaan yksinkertainen esimerkki: kertolasku.

        Kopioi Python-tulkkiin seuraavat rivit:

        import dis # tavukoodin disassembler
        dis.dis(lambda x,y: x*y) # (1)
        dis.dis(lambda x,y: [x]*y) # (2)

        Rivi (1) tulostaa tavukoodin funktiosta, joka kertoo kaksi parametrina saamaansa alkiota. Rivi (2) tulostaa tavukoodin funktiosta, joka tekee ensimmäisestä parametrista yhden alkion pituisen listan ja kertoo listan toisella parametrilla. (Pythonissa listan kertominen luvulla n tuottaa uuden listan, joka on vanha lista toistettuna n kertaa peräkkäin.)

        Vertaa sitten edellisten tavukoodien kertolaskun suorittavaa käskyä C-kääntäjän tuottamaan assemblyyn (valitse mieleisesi prosessoriarkkitehtuuri).

        Kertolasku kokonaisluvuilla:

        echo "int kerro(int x, int y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...pienillä kokonaisluvuilla...

        echo "char kerro(char x, char y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...isoilla kokonaisluvuilla...

        echo "long long kerro(long long x, long long y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...liukuluvuilla...

        echo "float kerro(float x, float y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        ...ja hieman tarkemmilla liukuluvuilla...

        echo "double kerro(double x, double y) { return x*y; }" | gcc -x c -c -o a.o - && objdump -d a.o

        Luultavasti näit aika monta eri käskyä pelkän kertolaskun suorittamiseen, ellet kääntänyt koodia 6502:lle. :)

        Mutta nuokaan käskyt eivät vielä suoriudu esim. listan monistamisesta. Kuitenkin kummallekin Python-funktiolle kävisi ensimmäiseksi parametriksi pienet luvut, isot luvut, liukuluvut, rajattoman tarkkuuden kokonaisluvut, listat ja merkkijonot ja monen muun tyyppiset arvot. Sama tavukoodi ja erityisesti sama kertolaskukäsky toimii silti.

        Toivottavasti tämä auttaa ymmärtämään eron tavukoodin ja konekielen välillä. Ne on suunniteltu hyvin erilaisiin tarkoituksiin. Konekielen suoritusta on vielä kohtuullisen helppoa simuloida softalla, mutta tavukoodiapa ei ajetakaan raudalla ihan helposti. Yhden ainoan tavukoodin käskyn suorittaminen saattaa kestää tunteja, vaikka prosessorissa gigahertsejä riittäisi jokaiselle sormelle.

        "Yritän selvittää tavukoodin ja konekielen eron vielä yhden kerran. Tavukoodi on suunniteltu ajettaviksi softalla."

        Eipä muuta sitä mihinkään vaikka näin olisi.

        "Siksi siinä voidaan käyttää ja käytetään sellaisia käskyjä, joita ei voi toteuttaa suoraan millään järkevällä raudalla."

        Kaikki käskyt on mahdollista toteuttaa raudalla. On eri asia onko siinä mieltä. Javan pinopohjainen tavukoodi on sitten huomattavan lähellä näitä jotka on suunniteltu ajettavaksi prosessorilla suoraan, ja tiedän sen, että Javan ajoon on tehty ihan suoraan rautatason ratkaisuja.

        Nykyaikana ei oikein pidetä x86:stakaan mielekkääksi ajaa raudalla..


    • opiskella...

      ...vähän lisää niin ei pääse lipsahtelemaan tällaisia sammakoita:

      >...voi tehdä sellaista mitä ceellä ei voi.

      Samalla voit miettiä sitä minkähän takia Torvalds ei anna koodata Linuxin kerneliä C :lla kuten Windowsit on tehty. ;)

    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. Mikä on totta mikä ei?

      Onko juoru vai ei että nimeltä mainitsematon henkilö on tehnyt naiselle/naisille jotain joka on väärin?
      Kuhmo
      21
      2294
    2. Päivän aivopieru Trumpilta

      Trump julisti sodan hyttysiä vastaan. Myös punkit ovat Trumpin sodan kohteena. Eikö vieläkään USA:n kansa tajua tuon uko
      Maailman menoa
      86
      1526
    3. Lopetetaanko tämä

      Juttu ja mennään eteenpäin? Pystytkö?
      Ikävä
      132
      968
    4. Just saying

      Mies joka antaa naiselle turvallisen olon, on seksikäs. Ei kieroja kikkoja ja haluaa olla vain sen yhden naisen mies.
      Ikävä
      142
      745
    5. Löytyikö syy miksi Martina on Muhiksen kanssa

      Saipa naurut Gekkosen kuvasta, missä ovat ravintola Hookissa Immu fight night ottelun jälkeen, Muhoksella pullottaa hirv
      Kotimaiset julkkisjuorut
      95
      682
    6. Voisin antaa sulle nyt

      Halin❤️
      Ikävä
      54
      676
    7. Janpen Thai lopettanut, miksiköhän

      Hyvää apetta teki.
      Suomussalmi
      13
      647
    8. Jorma Uotinen läväytti härskin heiton - Paljastus uudesta TTK-romanssista?

      Tuomari Jorma Uotisen linja on välillä hyvinkin rohkea TTK:ssa. Hän näpäytti Jaakko Parkkalille ja Kastanja Rauhalalle v
      Tanssii tähtien kanssa
      12
      608
    9. Jos selviäisi että kaivattusi

      Olisi savant asperger? Rakastaisitko vielä? Savant-lahjakkuus olisi kapea-alaista neroutta liittyen mekanisiin ja tilan
      Ikävä
      96
      602
    10. On väärin

      Tykätä ja haluta sua kun tilanne täysin mahdoton mutta minkäs teet. Mun sisällä roihuaa 🔥 kunpa tietäisit mitä sä minus
      Ikävä
      42
      562
    11. Tosi kiva on

      Joo. Mitä olisit menettänyt jos olisit paljastanut itsesi?
      Ikävä
      65
      561
    12. Toivotko vielä viestiä

      Minulta? En rohkene enää ottaa yhteyttä, kun varmasti jo uusia naisia elämässä. Nolaisin vain itseni.
      Ikävä
      44
      559
    13. Jokin ei täsmää

      Joskus yksi vuosiluku saa katsomaan koko tarinaa uudestaan. Löysin gradun. Matematiikka ei oikein täsmää siihen, mitä mi
      Ikävä
      298
      556
    14. Tehdään yhdessä itsestämme

      Parhaat versiot❤️ Se vaatii molemmilta hyvää itsetuntoa!
      Ikävä
      42
      525
    15. Olen ajellut Dieseleillä yli 50 vuotta.

      Enkä ole koskaan kaivannut sähköautoa.
      Hybridi- ja sähköautot
      138
      521
    16. Älä unohda minua

      Nainen ethän unohda minua. Asiat olisivat voineet mennä toisin, olisi vain pitänyt uskaltaa lähestyä sinua kun annoit si
      Ikävä
      66
      509
    17. Oliko Jani Halmeen aika jo tippua TTK:sta?

      Jani Halme ja Claudia Ketonen joutuivat jättämään TTK:n. Halme ja Ketonen saivat viimeiseksi jäänestä tanssista, sambas
      Tanssii tähtien kanssa
      28
      508
    18. Mitä tunteita

      Sulla vielä on?
      Ikävä
      77
      504
    19. Kuka kaipaa T m?

      Kerro nainen kirjaimesi vaan... Haluan miettiä kuka tulee ekana mieleeni.. kuin kurkistus tunteiden meren pinnalle, jota
      Ikävä
      36
      500
    20. Miksi jotku naiset on niin tyhmiä

      Että elättelevät turhaa toivoa toisen kustannuksella. Onko ne kaikki kaappilesboja vai mikä niitä vaivaa? Sitten itketä
      Ikävä
      54
      498
    Aihe