NULL C- ja C++ - ohjelmointikielissä on stddef.h- otsikkotiedostossa (ja muissa otsikkotiedostoissa) ilmoitettu makro . Tämän makron arvo on toteutuksesta riippuvainen nollaosoittimen vakio .
Nollaosoittimen vakio on kokonaislukuvakiolauseke, jonka arvo on 0 tai (vain C:ssä) sama lauseke, joka on muutettu tyyppiin void*. Nollaosoittimen vakio heitetty mihin tahansa osoitintyyppiin on nollaosoitin . On taattu, että nollaosoitin ei ole sama kuin osoitin mihinkään objektiin (laajemmassa merkityksessä mihin tahansa dataan) tai toimintoon. On taattu, että mitkä tahansa kaksi nollaosoitinta ovat yhtä suuret. Nollaosoittimen viittauksen poistaminen on toiminto, jolla on määrittelemätön toiminta .
Toisin sanoen toteutus antaa erityisen arvon - nollaosoittimen vakion, joka voidaan määrittää mille tahansa osoittimelle, ja tällainen osoitin ei verrattuna ole yhtä suuri kuin mikään "oikea" osoitin. Eli voidaan olettaa, että nollaosoitin ei sisällä kelvollista osoitetta muistissa.
Nollaosoittimet on suunniteltu käteväksi tavaksi "merkitä" osoittimia, joiden ei tiedetä osoittavan kelvolliseen muistiosoitteeseen. Esimerkiksi kun osoitin määritellään automaattiseksi muuttujaksi, sen arvo on määrittelemätön. Huomaa, että tämä osoitin ei vielä sisällä kelvollista osoitetta muistissa, tällaiselle osoittimelle on määritetty tyhjä osoitinvakio:
void f ( void ) { int * x = NULL ; /* ... */ }On hyvä ohjelmointityyli määrittää osoittimelle nollaosoitin sen viittauksen muistin vapauttamisen jälkeen. Lisäksi nollausosoittimien käyttö on tärkeää muistin vapauttamisen turvallisuuden kannalta: poistotoiminto C ++:ssa ( ilmainen C:ssä) on turvallista nollaosoittimelle. Esimerkiksi:
TYYPPI * foo = uusi TYYPPI (); //käyttää foo poistaa foo ; // foo != NULL // jokin ohjelmakoodi poistaa foo ; //VIRHE! muisti ei ole enää käytettävissätässä versiossa ei ole virheitä
TYYPPI * foo = uusi TYYPPI (); //käyttää foo poistaa foo ; // foo != NULL foo = NULL ; // foo == NULL // jokin ohjelmakoodi poistaa foo ; //ei virhettä: delete tarkistaa foo-arvonKun funktiota kutsutaan, NULL voidaan välittää jollekin argumentille. Makro NULL voidaan määritellä eri tavoin eri kääntäjissä, mukaan lukien
#define NULL 0
#define NULL ((void *)0)
Ensimmäisessä tapauksessa NULL on tyyppiä int, ja toisessa tapauksessa se on tyyppiä void*. On arkkitehtuureja, joissa sizeof(int) != sizeof(void*), niin eri alustoilla funktio saa eri määrän tavuja, mikä voi häiritä sen toimintaa. Tätä ongelmaa yritetään parhaillaan ratkaista C:ssä ottamalla käyttöön nullptr, katso ehdotus N 2394 [1] .
Nollaosoittimen viittauksen poistaminen on toiminto, jolla on määrittelemätön toiminta . Toteutuksella ei ole rajoituksia : esimerkiksi voi tapahtua pääsy muistiin, jota ei ole tarkoitettu tämän ohjelman käyttöön (eli luettaessa luetaan "roskaa" ja kirjoitettaessa arvo kirjoitetaan muistialue, joka ei kuulu ohjelmaan). Esimerkiksi DOSissa kirjoittaminen osoitteeseen nolla korvaa ainakin nollakeskeytysvektorin , joten seuraava kutsu int 0:lle todennäköisesti katkaisee järjestelmän. Tämä johtaa kuitenkin useimmiten ajonaikaiseen virheeseen (jos käyttöjärjestelmä toteuttaa muistisuojauksen ja pääsy prosessin varaamattomaan muistiin estetään). Esimerkiksi Windows 9x :ssä viesti "Yleinen suojausvirhe" - "Ohjelma suoritti laittoman toiminnan ja suljetaan" ( englanniksi yleinen suojausvirhe, GPF ) annetaan useimmiten tapauksissa, joissa ohjelma käyttää muistia virheellisten ( mukaan lukien alustamaton tai jo vapautettu) osoitin. Unix -tyyppisissä käyttöjärjestelmissä prosessi vastaanottaa tällaisissa tilanteissa SIGSEGV- signaalin ja sen käsittelijä tulostaa viestin " Segmentointivika ".
Jos otat tietyn NULL-toteutuksen lähdetiedostoissa, se voidaan määritellä muodossa (void*)0 tai 0. NULL:n käyttö C++-projekteissa voi johtaa virheisiin. Esimerkiksi
int ( Luokannimi ::* pf )() = NULL ;aiheuttaa käännösvirheen, jos NULL määritellään arvoksi (void*)0 (esimerkiksi otsikko sisällytettiin epäsuorasti, kun C++-standardi NULL-määritelmä on päällekkäinen). Siksi ei ole suositeltavaa käyttää NULL-arvoa muodossa ((void *)0) C++-ohjelmissa. C++11 - standardi lisää uuden avainsanan nullptr [2] [3] ilmaisemaan nollaosoittimen .