NULL în limbajele de programare C și C++ este o macrocomandă declarată în fișierul antet stddef.h (și alte fișiere antet). Valoarea acestei macrocomenzi este o constantă de indicator nul dependentă de implementare .
O constantă pointer nulă este o expresie constantă întreagă cu valoarea 0 sau (numai în C) aceeași expresie turnată la tip void*. O constantă de indicator nul turnată către orice tip de indicator este un pointer nul . Este garantat că un pointer nul nu este egal cu un pointer către orice obiect (în sensul cel mai larg, orice date) sau funcție. Este garantat că oricare doi pointeri nuli sunt egali. Dereferentarea unui pointer nul este o operație cu comportament nedefinit .
Cu alte cuvinte, implementarea oferă o valoare specială - o constantă pointer nulă, care poate fi atribuită oricărui pointer și un astfel de pointer, atunci când este comparat, nu va fi egal cu niciun pointer „corec”. Adică, putem presupune că un pointer nul nu conține o adresă validă în memorie.
Pointerii nuli sunt proiectați ca o modalitate convenabilă de a „marca” pointerii despre care nu se știe că indică către o adresă de memorie validă. De exemplu, atunci când se declară un pointer ca variabilă automată, valoarea acestuia este nedefinită. Pentru a reține că acest pointer nu conține încă o adresă validă în memorie, unui astfel de pointer i se atribuie o constantă pointer nulă:
void f ( gol ) { int * x = NULL ; /* ... */ }Este un stil de programare bun să atribuiți un pointer nul unui pointer după eliberarea memoriei la care face referire. În plus, utilizarea pointerilor de zero este relevantă pentru siguranța eliberării memoriei: operația de ștergere în C++ ( liber în C) este sigură pentru un pointer nul. De exemplu:
TIP * foo = TIP nou (); //utilizați foo șterge foo ; // foo != NULL // un cod de program șterge foo ; //EROARE! memoria nu mai este disponibilăîn timp ce în această versiune nu va exista nicio eroare
TIP * foo = TIP nou (); //utilizați foo șterge foo ; // foo != NULL foo = NULL ; // foo == NULL // un cod de program șterge foo ; //nicio eroare: delete verifică valoarea lui fooLa apelarea unei funcții, NULL poate fi transmis unuia dintre argumente. Macro-ul NULL poate fi definit în diferite moduri în diferite compilatoare, inclusiv
#define NULL 0
#define NULL ((void *)0)
În primul caz, NULL este de tip int, iar în al doilea caz, este de tip void*. Există arhitecturi în care sizeof(int) != sizeof(void*), apoi pe diferite platforme funcția va primi un număr diferit de octeți, ceea ce îi poate perturba funcționarea. În prezent se încearcă rezolvarea acestei probleme în C prin introducerea nullptr, vezi propunerea N 2394 [1] .
Dereferentarea unui pointer nul este o operație cu comportament nedefinit . Nu sunt impuse restricții asupra implementării : de exemplu, poate apărea un acces la memorie care nu este destinat utilizării de către acest program (adică la citire, „gunoi” va fi citit, iar la scriere, valoarea va fi scrisă în o zonă de memorie care nu aparţine programului). De exemplu, în DOS, scrierea la adresa zero va suprascrie cel puțin vectorul de întrerupere zero , așa că, cel mai probabil, următorul apel la int 0 va bloca sistemul. Cu toate acestea, aceasta duce cel mai adesea la o eroare de rulare (dacă sistemul de operare implementează protecția memoriei și accesul la memoria nealocată pentru proces este blocat). De exemplu, în Windows 9x , mesajul „Defecțiune generală de protecție” - „Programul a efectuat o operațiune ilegală și va fi închis” ( eroare generală de protecție în limba engleză , GPF ) este emis cel mai adesea în cazurile în care programul accesează memoria conform incorecte ( inclusiv indicatorul neinițializat sau deja eliberat). Pe sistemele de operare asemănătoare Unix , în astfel de situații, procesul primește un semnal SIGSEGV și handlerul său tipărește mesajul „ Efect de segmentare ”.
Dacă luați o implementare specifică a NULL în fișierele sursă, atunci aceasta poate fi definită ca (void*)0 sau ca 0. Utilizarea NULL în proiectele C++ poate duce la erori. De exemplu
int ( ClassName ::* pf )() = NULL ;va avea ca rezultat o eroare de compilare dacă NULL este definit ca (void*)0 (de exemplu, un antet a fost inclus indirect acolo unde definiția standard C++ a NULL se suprapune). Prin urmare, nu se recomandă utilizarea NULL în forma ((void *)0) în programele C++. Standardul C++11 adaugă un nou cuvânt cheie nullptr [2] [3] pentru a indica un pointer nul .