Paras vastaus
Kuten tiedämme, että tiedostossa määriteltyihin toimintoihin pääsee toisessa tiedostossa. Jos haluamme rajoittaa, että toimintoja ei saa kutsua toisessa tiedostossa, voimme tehdä niistä staattiset.
Siksi staattiset funktiot ovat niitä toimintoja, jotka ovat kutsuttavia samassa tiedostossa, jossa he määrittelevät .
Voimme määrittää funktion staattisen käyttämällä seuraavaa syntaksia
static return\_type function\_name(arguments)
{
function\_body;
}
Tässä on funktio, jolla etsitään tietyn luvun neliöjuuri
static long int getSquare(int num){
return (num*num);
}
Ohjelma näyttämään esimerkki staattisesta toiminnosta C-kielellä
#include
//static function definition
static long int getSquare(int num){
return (num*num);
}
int main()
{
int num;
printf("Enter an integer number: ");
scanf("\%d",&num);
printf("Square of \%d is \%ld.\n",num,getSquare(num));
return 0;
}
Tulos
Enter an integer number: 36
Square of 36 is 1296.
Miksi staattisia toimintoja tarvitaan?
Koska toimintoja käytetään koodin uudelleenkäyttöön (ts kirjoittamasi koodi pääsee toiseen tiedostoon asettamalla ne funktioihin ), mutta kun haluat määrittää joitain toiminnot, joiden ei pitäisi olla jaettavia (kutsuttavia) toisessa tiedostossa .
staattiset toiminnot ovat hyödyllisiä myös -ilmoitusristiriidan käsittelyssä – jos kahdessa eri tiedostossa on kaksi toimintoa, joilla on sama nimi, toimintoilmoitus on ristiriitainen. Voimme tehdä niistä staattiset.
Tällaisten vaatimusten täyttämiseksi voimme tehdä staattisiksi .
Vastaa
Lyhyt vastaus: Se tarkoittaa, että funktion nimi on näkyvissä ja soitettavissa vain parhaillaan koottavassa tiedostossa. Muut erikseen kootut tiedostot eivät näe funktion nimeä eivätkä voi kutsua sitä. Myöhemmin heillä voi olla omat staattiset toiminnot samalla nimellä. Tämä välttää nimiristiriidat tiedostojen sulkeumissa ja linkittämisessä objektitiedostoissa ja binaarikirjastoissa.
C-kirjastossa on 4 erilaista tallennustilaluokkaa. id = ”fbfd53b8ae”> auto (automaattinen) tämä on ”tavallinen” (oletus) ja käyttää avainsanaa auto , mutta on yleensä ei määritelty, koska se on oletusarvo.
- Nimeä ja tallennustilaa ei viedä muihin samanaikaisesti käännettäviin tiedostoihin. Tämä antaa jokaiselle tiedostolle samanlaiset nimet, jotka eivät ole ristiriidassa.
- Muuttujalle luotu tallennustila luodaan staattiselle tallennusalueelle ja alustetaan arvoon 0 ohjelman alkaessa tai nimenomaisella arvolla.
- Staattinen muuttuja alustetaan vain kerran . (kokoamisajankohtana). Sen jälkeen määritetyt arvot säilytetään ohjelman koko käyttöiän ajan tai kunnes tehtävä muuttaa niitä.
- Funktioiden sisällä ilmoitetulla staattisella tallennustilalla on toiminnon laajuus, mutta staattinen allokointi. Tämä tarkoittaa, että tallennustila on pysyvä koko ohjelman ajan, eikä sitä luoda, kun toimintopinokehys on varattu toimintokutsulle. Se säilyttää arvonsa useiden toimintokutsujen avulla. Tallennustila jatkuu, vaikka koodilohko palautetaan pinosta sen palattuaan.
int accumulate( unsigned int x)
{
static unsigned int acc = 0;
acc = acc + x;
return acc;
}
- Yllä olevat palaisivat juokseva summa tulostaan, koska var acc säilyttäisi arvon jokaisen puhelun kautta. acc alustetaan arvoon 0 ohjelman lataamisen yhteydessä.
- staattisilla muuttujilla on osoitteet RAM-muistissa, ja voit lähettää ne funktioihin viitteen tai arvon perusteella.
- Pienemmät muuttujat (määritelty funktioiden sisällä), joilla on sama nimi kuin staattisella muuttujalla kyseisen alueen ulkopuolella, varjostavat staattista muuttujaa samalla tavalla kuin muutkin.
- staattisia muuttujia ei välttämättä ole viedään ulkopuolisiin tiedostoihin, joten arvot voivat kadota kokoelma-alueista, ellei niitä nimenomaisesti lähetetä parametreina arvon mukaan. (gotcha!)
- Kuten 4, muutkin tiedostot eivät voi käyttää staattisia muuttujia ulkoisena , kuten ne voisivat käyttää automaattiset (normaalit) muuttujat. Se ei toimi, saat viallisia ohjelmia, jotka kaatuvat, ja kääntäjä saattaa hämätä ja kaipaamaan sitä.
- Staattiset muuttujat voidaan alustaa heidän ilmoituksessaan, mutta alustusarvon on oltava vakioilmainen, arvioitavissa käännösajassa, ei arvoa, jota ei voida laskea kokoamisajankohtana. Et voi alustaa staattista muuttujaa tuntemattomalla arvolla, kuten parametrimuuttujalla, tai tulos funktion kutsusta, jota ei ole tapahtunut kääntämisajankohtana.
int accumulate( unsigned int x)
{
/* ERROR x is not a compile-time constant. */
static unsigned int acc = x;
static unsigned int acc = 0; /* OK */
acc = acc + x;
return acc;
}
Staattiset toiminnot
- C: n staattisella toiminnolla on tiedostomuoto . Staattista toimintoa ei voida kutsui toinen tiedosto samassa käännösyksikössä. Käännösyksikkö on kaikki lähdekoodi, joka menee kääntäjään kerralla käännettävän esikäsittelyn jälkeen. Staattiset toiminnot eivät voi käyttää staattisia muuttujia tai kutsua staattisia toimintoja muista tiedostoista. Joten jos haluat rajoittaa toiminnon käyttöoikeuden nykyiseen tiedostoon, voit tehdä siitä staattisen. Tiedostossa voi olla vain yksi kyseisen niminen toiminto (joka pätee myös tavallisiin toimintoihin), joten usein apuohjelmatoiminnot laitetaan otsikkotiedostoihin sisällytettäviksi useisiin kokoelmiin, ja otsikkoa suojataan esiprosessorikomennoilla, jotta ei sisällytettävä mihin tahansa kokoamisyksikköön useammin kuin kerran. Kaikki C-standardin kirjaston otsikot ovat täynnä globaaleja toimintoja, ja niitä valvotaan siten, että ne kootaan vain kerran kokoelmassa, ja ne ovat globaaleja toimintoja. Ei staattisia toimintoja. Staattisilla funktioilla sanotaan olevan ’sisäinen linkitys’ , mikä tarkoittaa, että niitä ei voida nähdä muissa käännetyissä moduuleissa, vaikka ne olisikin linkitetty samaan lopulliseen ohjelmaan tai kirjastoon. Jos funktio ei ole staattinen , niin C: ssä funktio on globaali funktio ja se on käytettävissä koko ohjelmassa globaalisti. Tämä tarkoittaa, että koko ohjelmassa voi olla vain yksi funktio nimeltä print . Voit kiertää tämän tekemällä funktiot ja muuttujat staattisiksi, eikä sinulla ole nimien ristiriitaa.
- Toiminnot ovat globaaleja ja ulkoisia oletuksena paitsi tiedostossa, jossa ne on määritelty. Et siis näe sanaa extern käytetään C-lähteessä, jossa on funktioita, koska se on jo implisiittisesti olemassa. Siksi voit kutsua normaaleja toimintoja mistä tahansa käännösyksikön tiedostosta. Niiden sanotaan olevan ulkoinen linkitys , kun ne on linkitetty, ne ovat näkyvissä ja niitä voi kutsua mikä tahansa moduulin tiedosto tai mikä tahansa muu linkitetyn ohjelman moduuli.
- Funktion prototyypin ilmoitus on ”alustava määritelmä”, joka on implisiittisesti ulkoinen . Koodi sen jälkeen, kun prototyyppi-ilmoitus on skannattu ensimmäistä kertaa, voi kutsua toimintoa, kunhan lopullinen koodi sisältää täydellisen määritelmän. Tämä tarkoittaa, että ”todellisen määritelmän” on oltava olemassa tai muuten linkitysvaihe epäonnistuu. Siksi C: n otsikot eivät yleensä sisällä toimintojen lähdekoodia, niitä ei tarvita kääntämiseen, mutta ne ovat linkitysvaiheessa.
- Staattisen funktion prototyyppideklarointi on ”alustava määritelmä”, joka ei nimenomaisesti ole ulkoinen . Koko määritelmän on oltava läsnä nykyisessä käännösyksikössä (käännetty samanaikaisesti), muuten kokoaminen epäonnistuu. Nykyaikaiset C-kääntäjät syntetisoivat prototyypin määritelmästä, kunhan se tapahtuu aikaisemmin kuin varsinainen toimintokutsu. Niin sanotut ”ennakkoilmoitukset” sallivat alustavien määritelmien käytön varsinaisen määritelmän kanssa myöhemmin, ja niillä on erilaisia käyttötarkoituksia tietorakenteissa ja kirjastojen organisaatiossa.
- Tiedoston allekirjoituksen ensimmäinen määritelmä on määritelmä koko ohjelmalle, mukaan lukien staattinen tai ulkoinen. Kun funktio on määritelty ensimmäisen kerran, se julistetaan aluksi staattiseksi, se on aina staattinen, vaikka se määriteltäisiin myöhemmin uudelleen ilman staattista avainsanaa. Jos se ilmoitetaan alun perin ulkoiseksi (oletus), sitä ei voida määrittää uudelleen staattiseksi.
static void f(int); /* Function is always static */
...
void f(int x) { ….} /* static , not exported, no error */
void f(int); /* Function is always global */
...
static void f(int x) { ….} /*ERROR NOT STATIC */
clang: "error: static declaration of "f" follows non-static declaration"
- Lohkon laajuudessa määriteltyjä toimintoja ei voida julistaa staattisiksi. Vain tiedostomäärän staattiset funktiomääritykset voidaan tehdä minkä tahansa lohkon ulkopuolelle. Tällä on järkeä logiikan näkökulmasta, koska tiedostojen laajuutta ei voida tehdä pienemmäksi kuin koko tiedosto. Määritä siis staattinen funktio tai ainakin prototyyppi tiedoston varhaisessa vaiheessa.
- Staattinen viittaa funktioon, ei palautustyyppiin . Voit sijoittaa staattisen avainsanan palautustyypin jälkeen, jos haluat, mutta jos olet, olet outo ja hämmentät ihmisiä. Palautusarvo ei ole staattinen, vaan funktio on.
- Staattinen funktion määritelmä ei korvaa globaali, joka on määritelty ennen sitä samassa tiedostossa tai mukana olevassa tiedostossa. Jos tällä nimellä on jo määritetty funktio, et voi määritellä sitä uudelleen staattisella funktiolla tai millä tahansa saman nimisellä funktiolla.
C ei nimeä funktioita ja muuttujia sisäisesti uudelleen kuten C ++, joten se ei tue toimintojen ylikuormitusta. C ++ ”sekoittaa” funktioiden nimet koodatulla nimellä, joka osoittaa useita ylimääräisiä tietoja, kuten jos se kuuluu luokkaan tai mitkä ovat sen parametrit jne. Joten C: ssä ilman staattista avainsanaa sinulla voi olla vain yksi funktio jokainen ohjelman yksilöllinen nimi riippumatta siitä, kuinka monta tiedostoa tai kirjastoa se sisältää.
Joten mitä teet, jos haluat muuttaa toimintoasi jo olemassa olevalle aikaisemmalle?
No, mitä älykkäät C-kooderit tekevät, on keksiä eri nimi toiminnalleen. Mutta on tapa ”huijata” kääntäjää muuttamalla ennakoivasti lähdeteksti esiprosessorilla.
Esimerkki: Joku idiootti kirjoitti kirjastoonsa int sort( char** Array)
-funktion. ja teki siitä globaalin, ja se on buginen eikä tee juuri sitä mitä haluat, koska se saa numerot tulemaan kirjainten tai jonkin muun jälkeen, ja T-sanat ovat aina etusijalla jostain syystä.
Haluat käytä kirjastoa, mutta toiminto on korjattava, ja sinulla on vain otsikot ja käännetty kirjasto, ei lähdekoodia.
OK> joten tehdään erityinen otsikko, joka korvaa kaikki lajittele ”otsikossa” bad\_sort ”, tuo sitten koodisi ja korvaa kaikki” sort ”-ilmentymät” good\_sort ”-asetuksilla. ”Good\_sort” on määritelty kokonaan muodossa good\_sort.h, mutta on merkitty staattiseksi, joten se tunnetaan vain tiedostossa, johon se sisältyy.
/* good\_sort.h */
#ifndef \_GOOD\_SORT\_H
#define \_GOOD\_SORT\_H
static int good\_sort(char** Array)
{
... //code here
return numsorted;
}
#endif
Määritelmän suojakannake lisätään sen varmistamiseksi, ettei sitä sisälly kahdesti.
/*-----------------------------------*/
/* program.c */
#include "Trumpsort.h" /* The buggy library header */
...
#ifdef sort
#undef sort /* undefine the sort function name as reserved */
#define sort bad\_sort /* replace the name */
#include "good\_sort.h" /* your fixed version */
#endif
#define sort good\_sort /* replace the name in this file */
/* rest of file */
Hieman paskaa, mutta idea on kutsua funktiosi renam-nimisen huonon sijasta sille ”hyvä\_laji” ja kutsumalla sitä sen sijaan. (mutta vain tässä tiedostossa – staattinen ).