Kysymys:
Mitä eroa on muuttujan ilmoittamisen silmukan ulkopuolella ja staattisen sisäisen silmukan välillä ilmoittamisen välillä?
Cybergibbons
2014-03-01 16:00:29 UTC
view on stackexchange narkive permalink

Nämä ovat kaksi tapaa pitää muuttuja silmukan (tai minkä tahansa toiminnon) ulkopuolella.

Ensinnäkin voin ilmoittaa sen globaalilla laajuudella silmukan ulkopuolella:

  void setup () {Sarja.alku (9600);} int count = 0; void loop () {Sarja.println (määrä); laskea ++; delay (250);}  

Voin myös julistaa sen staattiseksi silmukan sisällä:

  void setup () {Serial.begin (9600);} void loop () {staattinen int-määrä = 0; Serial.println (määrä); laskea ++; delay (250);}  

Mitä eroa sillä on, jos sellaista on?

Neljä vastused:
#1
+10
asheeshr
2014-03-01 16:45:20 UTC
view on stackexchange narkive permalink

Perusero on laajuus.

Ensimmäisessä tapauksessa ilmoitat globaalin muuttujan. Se on muuttuja, joka on käytettävissä kaikilla alueilla määritelmänsä jälkeen.

  void setup () {Serial.begin (9600);} void inc (); int count = 0; void loop ( ) {Sarja.println (määrä); laskea ++; inc (); delay (500);} void inc () // Voi muokata määrän {count = count + 1;};  

Toisessa tapauksessa ilmoitat staattisen muuttujan paikallisesti. Muuttuja säilyy koko ohjelman ajaksi samanlaisena kuin globaalit muuttujat, mutta siihen pääsee vain siinä koodilohkossa, johon se on ilmoitettu. Tämä on sama esimerkki, vain yksi muutos. count on nyt ilmoitettu staattisena muuttujana loop.

  void inc (); void loop () {staattinen int count = 0 ; Serial.println (määrä); laskea ++; inc (); delay (500);}  

Tätä ei käännetä, koska funktiolla inc () ei ole pääsyä count -kohtaan.

Globaaleissa muuttujissa, vaikka näyttäisikin siltä hyödyllisiltä, ​​on joitain sudenkuoppia. Nämä voivat jopa vahingoittaa fyysisen ympäristön kanssa vuorovaikutuksessa olevien ohjelmien kirjoittamista. Tämä on hyvin yksinkertainen esimerkki jostakin todennäköisestä tapahtumasta heti, kun ohjelmat alkavat suurentua. Toiminto voi vahingossa muuttaa globaalin muuttujan tilaa.

  void setup () {Serial.begin (9600);} void another_function (); int state = 0; void loop () { // Jatka tilan vaihtamista Serial.println (tila); viive (250); tila = tila? 0: 1; // Jotkut etuyhteydettömät funktiot kutsuvat toinen_toiminto ();} mitätöivät toisen toiminnon () {// Tahattomasti muuttavat tilan tilaa = 1;}  

Tällaisia ​​tapauksia on erittäin vaikea selvittää. Tämän tyyppinen ongelma voidaan kuitenkin helposti havaita yksinkertaisesti staattisen muuttujan avulla.

  void setup () {Serial.begin (9600);} void another_function (); tyhjä silmukka () {staattinen int-tila = 0; // Jatka tilan vaihtamista Serial.println (tila);
viive (250); tila = tila? 0: 1; // Jotkut etuyhteydettömät funktiot kutsuvat another_function ();} void another_function () {// Tuloksena on käännösvirhe. Säästää aikaa. tila = 1;}  
#2
+5
Philip Allgaier
2014-03-01 16:49:55 UTC
view on stackexchange narkive permalink

Toiminnallisesta näkökulmasta molemmat versiot tuottavat saman tuloksen, koska molemmissa tapauksissa count -arvo tallennetaan -silmukan () suoritusten väliin (joko siksi, että se on globaali muuttuja tai koska se on merkitty staattiseksi ja pitää sen vuoksi arvonsa).

Joten valitsemasi päätös tulee seuraaviin argumentteihin:

  • Yleensä tietojenkäsittelytieteessä kannustetaan pitämään muuttujat mahdollisimman paikallisesti laajuuden kannalta. Tämä johtaa yleensä paljon selkeämpään koodiin, jossa on vähemmän sivuvaikutuksia, ja vähentää mahdollisuuksia, että joku muu käyttää tätä globaalia muuttujaa ruuvaamaan logiikkasi). Esim. ensimmäisessä esimerkissä muut logiikka-alueet saattavat muuttaa count -arvoa, kun taas toisessa vain kyseinen funktio loop () voi tehdä sen).
  • Globaalit ja staattiset muuttujat vievät aina muistin , missä paikalliset vain, kun ne ovat soveltamisalassa. Yllä olevissa esimerkeissäsi ei ole merkitystä (koska yhdessä käytetään globaalia, toisessa staattista muuttujaa), mutta isommissa ja monimutkaisemmissa ohjelmissa se saattaa ja voit säästää muistia käyttämällä ei-staattisia paikallisia. vähän aikaa muistin varaamiseen tälle uudelle muuttuja-ilmentymälle. Sinun on löydettävä tasapaino muistikuormituksen ja suorituskyvyn välillä.
  • Myös muita kohtia, kuten kääntäjän staattisen analyysin tai optimoinnin parempi asettelu, saattaa tulla.
  • Joissakin erityistilanteissa staattisten elementtien arvaamattomassa alustamisjärjestyksessä saattaa olla ongelmia (ole varma siitä, vertaa kuitenkin tätä linkkiä).
  • Lähde: Samankaltainen ketju sivustolla arduino.cc

    Uudelleenvalinnan ei pitäisi koskaan olla Arduinon ongelma, koska se ei tue samanaikaisuutta.
    Totta. Se oli enemmän yleinen asia, mutta ei todellakaan ole merkitystä Arduinolle. Poistin sen.
    Alueen sisällä ilmoitettu staattinen muuttuja on aina olemassa ja käyttää samaa tilaa kuin globaali muuttuja! OP-koodissa ainoa ero on siinä, mikä koodi pääsee muuttujaan. Staattisesti pääsee käsiksi samassa laajuudessa.
    @jfpoilpret Se on tietysti totta, ja näen, että vastaukseni vastaava osa oli hieman harhaanjohtava. Korjattu.
    #3
    +2
    JRobert
    2014-03-03 04:11:53 UTC
    view on stackexchange narkive permalink

    Molemmat muuttujat ovat staattisia - ne säilyvät koko suoritusistunnon ajan. Globaali näkyy kaikille funktioille, jos se ilmoittaa - ei määrittele - globaalin tai jos funktio seuraa määritelmää samassa kokoamisyksikössä (tiedosto + sisältää).

    count -määrityksen siirtäminen toiminnon sisäpuolelle rajoittaa sen näkyvyyden vain lähimpään sulkeutuvaan {} esjoukkoon ja antaa sille toiminnon kutsun käyttöiän (se luodaan ja tuhotaan, kun funktio syötetään ja poistunut). Sen julistaminen staattiseksi antaa sille myös suoritusistunnon käyttöiän, joka se on olemassa suoritussession alusta loppuun, jatkuen kaikissa toimintokutsuissa.

    BTW: Ole varovainen alustettujen staattisten ominaisuuksien suhteen. funktion sisällä, koska olen nähnyt joidenkin gnu-kääntäjän versioiden saavan tämän väärin. Jokaiselle funktiomerkinnälle tulisi luoda ja alustaa automaattinen muuttuja, jossa on alustus. Staattinen, jossa on alustus, tulisi alustaa vain kerran, suorituksen määrityksen aikana, ennen kuin main (): lle annetaan ohjaus (aivan kuten globaali olisi). Minulla on ollut paikalliset staatiot alustettu uudelleen jokaisessa funktiomerkinnässä ikään kuin ne olisivat automaattisia, mikä on väärin. Testaa oma kääntäjäsi varmistaaksesi.

    En ole varma, ymmärränkö mitä tarkoitat toiminnasta, joka julistaa maailmanlaajuisen. Tarkoitatko "ulkoisena"?
    @PeterR.Bloomfield: En ole varma, mistä viestistäni kysyt, mutta viittasin OP: n kahteen esimerkkiin - ensimmäiseen, luonnostaan ​​globaaliin määritelmään ja toiseen, paikalliseen staattiseen.
    #4
    -3
    Void Main
    2014-03-01 16:41:46 UTC
    view on stackexchange narkive permalink

    Atmelin dokumentaation mukaan: "Jos ilmoitetaan globaali muuttuja, tälle muuttujalle osoitetaan SRAM: n yksilöllinen osoite ohjelman linkityksen aikana."

    Täydellinen dokumentaatio on täällä (vinkki # 2 globaaleille muuttujille): http://www.atmel.com/images/doc8453.pdf

    Eivätkö molemmat esimerkit päädy yksilölliseen osoitteeseen SRAM: ssä? Heidän molempien on jatkettava.
    Kyllä, tosiasiallisesti löydät kyseisen tiedon samasta asiakirjasta vinkistä # 6


    Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
    Loading...