What is a pointer in C?
A pointer is a variable that stores the address of another object.
&xtakes an address,*preads or writes the object behind it, and the pointer's type gives*pandp + 1the object's size.C#include <stdio.h> int main(void) { int x = 10; int *p = &x; /* p holds the address of x */ *p = 25; /* write through the pointer */ printf("x = %d, *p = %d\n", x, *p); printf("p points to x: %s\n", p == &x ? "yes" : "no"); return 0; }It prints
x = 25, *p = 25andyes. More in pointers in C.What is the difference between a NULL pointer, a void pointer, a dangling pointer and a wild pointer?
A NULL pointer points to nothing and can be tested. A
void *is a generic pointer with no type; convert it before use (it can be NULL too). A dangling pointer points to freed or out-of-scope memory, and a wild one was never initialized; dereferencing either is undefined behavior. Initialize every pointer and set it toNULLafterfree.What is a void pointer, and why can you not dereference it?
A
void *holds the address of any object type, which is howmalloc,qsortandmemcpystay generic. You cannot dereference it because the compiler does not know the size or type behind it; convert it first.C#include <stdio.h> void print_value(const void *p, char type) { if (type == 'i') printf("int: %d\n", *(const int *) p); if (type == 'd') printf("double: %.2f\n", *(const double *) p); } int main(void) { int i = 42; double d = 3.14159; print_value(&i, 'i'); print_value(&d, 'd'); return 0; }Arithmetic on
void *is not standard C (GCC allows it with size 1), so usechar *for byte offsets.Which variable does
**q = 20change whenqpoints top?C#include <stdio.h> int main(void) { int x = 10; int *p = &x; int **q = &p; **q = 20; printf("%d\n", x); return 0; }It prints
20.*qispand**qisx, so**q = 20writes tox. A function takes a pointer to a pointer when it must change the caller's pointer:void make_buffer(char **out, size_t n) { *out = malloc(n); /* changes the caller's pointer */ }What is the difference between
const int *p,int *const pandconst int *const p?const int *ppoints to a const int:pcan move but*pcannot be written.int *const pis a const pointer:*pcan be written butpcannot move.const int *const pallows neither. Read right to left;constapplies to what is on its left, or its right if nothing is on its left. Useconst T *for read-only parameters, asstrlendoes.What is the difference between
*(p + 2)and*p + 2?C#include <stdio.h> int main(void) { int a[] = {10, 20, 30, 40}; int *p = a; printf("%d %d\n", *(p + 2), *p + 2); return 0; }It prints
30 12.p + 2moves twoints forward, scaled bysizeof(int), so*(p + 2)isa[2].*binds tighter than+, so*p + 2isa[0] + 2. See pointer arithmetic.What is a function pointer, and where is it used?
A function pointer stores a function's address so you can call it later or pass it on, declared as
return_type (*name)(params). C uses it for callbacks and dispatch tables.C#include <stdio.h> #include <stdlib.h> int cmp_asc(const void *a, const void *b) { int x = *(const int *) a, y = *(const int *) b; return (x > y) - (x < y); } int main(void) { int (*cmp)(const void *, const void *) = cmp_asc; int v[] = {5, 2, 9, 1, 7}; qsort(v, 5, sizeof v[0], cmp); for (int i = 0; i < 5; i++) printf("%d ", v[i]); printf("\n"); return 0; }It prints
1 2 5 7 9. The comparator avoidsx - y, which overflows for large values of opposite sign. See function pointers.What is the difference between
int *p[3]andint (*p)[3]?int *p[3]is an array of 3 pointers;int (*p)[3]is one pointer to an array of 3 ints.[]binds tighter than*, so the parentheses decide.C#include <stdio.h> int main(void) { int a = 1, b = 2, c = 3; int *arr_of_ptrs[3] = {&a, &b, &c}; int grid[2][3] = {{1, 2, 3}, {4, 5, 6}}; int (*row)[3] = grid; /* points to grid[0] */ printf("sizeof arr_of_ptrs: %zu\n", sizeof arr_of_ptrs); printf("sizeof row: %zu\n", sizeof row); printf("*arr_of_ptrs[1] = %d\n", *arr_of_ptrs[1]); printf("row[1][2] = %d\n", row[1][2]); /* row + 1 skips a whole row */ return 0; }Here the array is 24 bytes and the pointer 8. A 2D array decays to a pointer to an array, so
row + 1skips a whole row.What does the
restrictkeyword mean?restrict(C99) promises that, for the pointer's lifetime, an object it points to that is modified is accessed only through that pointer (or one derived from it). The compiler can then assume no overlap and vectorize.void add(int n, float *restrict out, const float *restrict a, const float *restrict b) { for (int i = 0; i < n; i++) out[i] = a[i] + b[i]; }Breaking the promise is undefined behavior and is not checked.
memcpydeclares its parametersrestrictfor this reason: its buffers must not overlap. C++ has norestrictkeyword.What is the difference between
*p++,(*p)++and*++p?Postfix
++binds tighter than*, so*p++is*(p++): it reads the current element, then moves the pointer.(*p)++adds 1 to the value and leaves the pointer alone, and*++pmoves the pointer first, then reads.C#include <stdio.h> int main(void) { int a[] = {10, 20, 30}; int *p = a; int x = *p++; /* reads a[0], then moves p to a[1] */ printf("%d %d\n", x, *p); int y = (*p)++; /* reads a[1], then adds 1 to a[1] */ printf("%d %d\n", y, a[1]); int z = *++p; /* moves p to a[2], then reads it */ printf("%d\n", z); return 0; }It prints
10 20,20 21and30.*p++is the idiom behind copy loops such aswhile ((*dst++ = *src++)). See pointer arithmetic.
C Pointers Interview Questions
The topic C interviews spend most time on: invalid pointers, const, function pointers and pointer arithmetic.