const int *a;
a = NULL; // perfectly OK
*a = 0; // does not compile
Is a pointer to a constant int, not a constant pointer to an int. int *const a;
a = NULL; // does not compile
*a = 0; // perfectly OK
Which is a constant pointer to a regular int. const int *const a;
a = NULL; // does not compile
*a = 0; // does not compile
Which is a constant pointer to a constant int (which, of course, makes no sense at all in this case since 'a' is uninitialized and cannot be initialized without an unsafe cast, but it's a perfectly valid statement in C).
Example: when performing a context switch in a kernel, assembly is required since C abstracts away architecture-specific details necessary to swap out the register set, swap the page directory pointer, etc.