Lueskelin tuossa putkan C ohjelmointi opasta ja mietin että toimiiko for silmukka säännöt samalla tavoin kuin javassa.
Eli voiko C kielessä for loopin kirjoittaa näin.
Tai siis kokeilin ja toimii eli voi kirjoittaa, mutta onko se oikea tapa ?
Ja tarkoitan i:n alustusta tuolla tavoin.
for(int i = 1; i <= kierrosMaara; i++)
{
}
Vai pitääkö se alustaa esim. nollaksi ensin ja loopissa asettaa alkuarvo uudelleen ??
int i = 0;
for(i = 1; i <= kierrosMaara; i++)
{
}
Se on vain syntaksin etu. Eli ihan vapaasti. Ja muutenkin muuttujamääritteen vaikutus on vain tuon loopin sisäinen, joten sen viemä muisti ei vaikuta muualla ohjelmaa (käsittääkseni).
Vastaus riippuu siitä, mikä C-standardi on käytössä:
C90: Muuttujaa ei saa määritellä for-silmukassa.
C99: Muuttujan saa määritellä for-silmukassa.
Eli jos käytät kääntäjää, joka tukee (tuolta osin) C99-standardia, voit määritellä muuttujan for-silmukassa. Joskus kääntäjälle täytyy erikseen ilmoittaa, että haluaa käyttää C99-standardia.
Mielestäni tuollainen määrittely ei ole kuitenkaan "oikea tapa", koska se on vastoin perinteistä C-kielen käytäntöä. Jos ohjelma noudattaisi muuten C90-standardia, jota useimmat kääntäjät tukevat, on vähän turhaa vaatia uudempaa C99-standardia tuollaisen pikkuasian tähden.
Ville kirjoitti:
Vai pitääkö se alustaa esim. nollaksi ensin ja loopissa asettaa alkuarvo uudelleen ??
Muuttujalle ei tarvitse antaa (hyödytöntä) alkuarvoa määrittelyssä:
int i; for (i = 1; i <= kierrosMaara; i++)
Tai jos alkuarvon antaa määrittelyssä, sitä ei tarvitse antaa silmukassa:
int i = 1; for ( ; i <= kierrosMaara; i++)
Käytännössä tuo ylempi tapa on järkevä for-silmukan toteutustapa.
Kuten tuossa jo mainitsinkin on nuo java kuviot ja ympäristöt hiukan tutummat.
Aloitte puhumaan C:n standardeista, onko niitä kuinkakin monta ja eikös se tee ohjelman kehityksestä vaikean ?
Nimittäin jos teen ohjelman ja käyttäjällä ei olekaan samaa standardia, niin ei toimi, olenko ymmärtänyt standardin vaikutuksen oikein ?
Käytössäni bloodshedin Dev-C++ ide (vai luetaanko se editoreihin) näihin C kokeiluihin.
Mistä saan selville mikä standardi minulla on käytössä ?
C-kielen standardeja on kaksi, C90 ja C99. Useimmat kääntäjät tukevat C90-standardia ja jotkin ainakin osittain myös C99-standardia.
Standardilla on merkitystä siinä vaiheessa, kun ohjelma käännetään. Jos koodissa on kohtia, jotka ovat sallittuja vain C99-standardissa, kääntäjän täytyy vastaavasti tukea C99-standardia. Käännöksen tuloksena syntyy konekielinen ohjelma, joka toimii yhtä lailla kaikilla käyttäjillä.
Toisin sanoen käytetty standardi voi aiheuttaa ongelmia vain sille henkilölle, jonka tehtävänä on kääntää ohjelman koodi suoritettavaan muotoon. Käännetyt C-kieliset ohjelmat eivät tarvitse tuekseen virtuaalikonetta tms., josta olisi olemassa monta eri versiota. Tietenkään Windows-ohjelmat eivät toimi Linuxilla jne., mutta tämä ei liity C-standardeihin.
Kun käytössäsi on Dev-C++, kääntäjäsi on varmaankin gcc, joka taitaa tukea C90-standardia ja osittain C99-standardia. Jos pystyt kääntämään ohjelman, jossa muuttujan määrittely on for-silmukassa, kääntäjäsi tukee C99-standardia ainakin tämän piirteen osalta.
Niin, siis voimassaolevia C-kielen standardeja on yksi: ns. C99 eli ISO/IEC 9899:1999 ja siihen tehdyt korjaukset (Technical Corrigendum) 1, 2 ja 3, joista viimeisin vuodelta 2007.
Ikävä kyllä kaikki C-kääntäjät eivät kymmenenkään vuoden jälkeen noudata standardia kaikilta osiltaan. Ja työn alla on sentään jo uusikin standardi, ISO/IEC 9899:201x.
Muuttujien esittely suoritettavan koodin lomassa, mukaan lukien for-luupin muuttujien näkyvyysalue, on nykystandardin mukaista. On vähän löysää puhetta sanoa, ettei se ole C-kielen käytännön mukaista; eipä kai, kun se ei ole ennen nykystandardia ollut edes "lain" mukaista! Mutta nyt on. Jotkut kääntäjät eivät tätä noudata tai vaativat jonkun asetuksen käyttämistä.
Muuttujaesittelyjen nykysäännöt on omaksuttu C++:n mallin mukaan. Muuttujien esittely (ja alustaminen) siellä, missä niitä käytetäänkin, vähentää ns. typeriä ohjelmointivirheitä.
Jos vaihtoehtoina ovat C ja C++, valitsen itse kyllä C++:n. C++ kattaa C:n pääosiltaan, tarjoaa tyypillisesti turvallisemman ratkaisutavan, on oikeastaan lähempänä "C:n henkeä" kuin nyky-C, eikä ole teholtaan yhtään heikompi. Mutta tämä nyt ei taida liittyä alkuperäiseen kysymykseen muuta kuin siltä osin, että C++:ssa muuttujia siis esitellään ihan tavanomaisesti koodin lomassa, myös noissa for-luuppien alustuksissa.
Voisin hyvin kuvitella, että muuttujien esittely koodilohkojen alussa saa useimmat harkitsemaan algoritmiaan, ja koodistakin tulee selkeämpää. ANSI C:n paras puoli on toki se, että kaikki kääntäjät sitä tukevat.
Mitään syytä en näe myöskään sille, että em. käytännöstä aiheutuisi vakavampia ohjelmointivirheitä. Aloittelija, jonka ajatus jää kirjoitusnopeudesta seuraavaksi, voi tietotyyppien kanssa tietysti epäonnistua, mutta kääntäjähän viimeistään on tässä suhteessa ystävä.
Javassakaan muuttujaa ei tarvitse alustaa moneen kertaan, eli myös siinä toimii tämä perinteinen, C90-yhteensopiva tapa:
int i; for (i = 0; i < 10; ++i) { /* [0, 9] */ } for (i = 100; i > 15; --i) { /* [100, 16] */ }
Standardeista täytyy mainita vielä, että useimmat kääntäjät eivät normaalisti noudata mitään näistä virallisista standardeista vaan kelpuuttavat kaiken, mitä kääntäjä sattuu tukemaan. GCC:n normaali "standardi" sallii kymmenittäin asioita, joita ei ole kirjattu sen paremmin C:n kuin C++:nkaan mihinkään standardiin tai jotka on jopa kielletty. Tietyn standardin voi asettaa päälle sopivilla käännösasetuksilla. Esimerkiksi GCC:n parametri -std=c99
määrää standardiksi C99:n.
Standardin tukeminen kohdekoneella voi aiheuttaa pieniä ongelmia dynaamisesti linkitettyjen ohjelmien kanssa. Useinhan C:n standardikirjaston funktioita ei turhaan sisällytetä ohjelmaan, koska ne kuitenkin löytyvät joka koneelta. Siksi esimerkiksi printf-funktion tietyt uudemmat formaatit (esimerkiksi "%zu") eivät välttämättä toimi. Toki funktiot voi kääntää myös staattisesti ohjelman mukaan, mutta tällöin ohjelmasta tulee tietenkin paljon isompi.
C:ssä muuttujamäärittelyjen sääntöjä on muutettu, koska sitä on pidetty hyödyllisenä. Yleisesti pidetään selkeänä ja vähiten virhealttiina tapaa, jossa paikalliset muuttujat ovat niin paikallisia kuin mahdollista. Jos esimerkiksi muuttujaa i
käytetään vain silmukkalaskurina, se on hyvä määritellä vain silmukan yhteydessä ja vieläpä vaikka jokaiselle silmukalle erikseen. Alustusten tekeminen muuttujien esittelyn yhteydessä ja esittelyjen tekeminen vain siellä, missä muuttujaa todella tarvitaan, vähentää käyttämättömistä tai alustamattomista muuttujista koituvia virheitä, sillä kaikissa tilanteissa kääntäjäkään ei niistä pysty huomauttamaan.
C:ssä asia ei ehkä tule niin vahvasti esiin, mutta paikallisten muuttujien suuremmasta paikallisuudesta koituu myös suorituskykyetuja.
Nyky-C:n säännöt paikallisten muuttujien esittelyistä ja näkyvyysaluista ovat itse asiassa yhdenmukaisia C++:n ja Javan kanssa. Kaikki nämä toki sallivat paikallisten muuttujien esittelemisen tavalla, joka aiemmin oli C:ssä ainoa mahdollinen.
Kääntäjän standardinmukaisuutta voi arvioida senkin mukaan, toteuttaako kääntäjä standardin vaatimukset ja toteuttaako kääntäjä vielä lisäpiirteitä, joita voidaan pitää laajennuksina. Perusvaatimusten osalta yleisimmät kääntäjät ovat kyllä aika kattavia.
Myös ANSI on vahvistanut nykyisen C-standardin kansalliseksi standardikseen kymmenkunta vuotta sitten.
Aihe on jo aika vanha, joten et voi enää vastata siihen.