În C, deoarece limbajul ofera o mare libertate de exprimare, este foarte usor pentru un programator neatent sa faca erori care nu sunt semnalate la compilare, dar care duc la comportari neasteptate ale programului.
O eroare tipica este atribuirea de valori pointerilor neinitializati:
int *un_pointer; *un_pointer=5;În aceasta situatie, deoarece un_pointer este neinitializat, valoarea 5 este scrisa în memorie la o locatie aleatoare, poate chiar rezervata altei variabile. În cazul în care un pointer nu arata spre o zona de memorie rezervata, trebuie alocata o zona de memorie în mod explicit, folosind functia malloc:
În C nu exista un mecanism de garbage collection, astfel ca programatorul trebuie sa aiba grija ca zonele de memorie alocate dinamic si care nu mai sunt utile sa fie dealocate (folosind functia free). Faptul ca unui pointer i se atribuie o noua valoare nu înseamna ca zona de memorie spre care arata s-a eliberat si în acest mod programul poate ajunge sa tina alocata toata memoria disponibila.
O alta greseala des întâlnita este referirea pointerilor spre alte locatii de memorie:
int obiect=5; int *obiect_ptr; obiect_ptr = obiect;Lipsa operatorului de adresa & face ca obiect_ptr sa indice spre locatia de memorie aflata la adresa 5.
Urmatorul exemplu ilustreaza un stil de programare "daunator", care strica lizibilitatea codului. Limbajul C este foarte flexibil, fapt ce poate duce, în special în cazul pointerilor, la rezultate imprevizibile:
void copy_string(char * p, char *q) { /* copiaza sirul q in p */ while (*p++ = *q++); }Chiar daca aceasta implementare este mult mai compacta, urmarirea codului este foarte dificila, iar folosirea combinata a operatorilor de incrementare si pointerilor poate duce la efecte necontrolate. Urmatoarea varianta de implementare a aceleiasi functii copy_string prezinta un stil adecvat programarii cu pointeri:
void copy_string(char * dest, char * sursa) { *dest = *sursa; while (*dest!='\0') { ++dest; ++sursa; *dest = *sursa; } }