Problem : Is the following piece of C code valid?

int main() { int *steve; steve = &steve; return 0; }

It will compile, but it's probably not what was intended. steve is a pointer to an integer, so the address of steve should be stored in a pointer to a pointer to an integer. In practice, all pointers are treated as integers, but the compiler will most likely complain about an assignment between incompatible types. A better way to write this is:
int main() { int *steve; int **psteve; psteve = &steve; return 0; }

Problem : What is wrong with the following code?

int main() { int *steve; *steve = 100; printf("%d\n", *steve); return 0; }

The pointer steve hasn't been assigned an address, so it still contains whatever random value was in the memory it occupies (whatever value was there before it was used for steve). As such, when we try to dereference steve and store the value 100 into it, we're attempting to store a value into some random piece of memory that our program most likely doesn't own. This will probably crash your program. To fix it, still using the same pointer idea, we would want something like:
int main() { int *steve; int a; steve = &a; *steve = 100; printf("%d\n", *steve); return 0; }

Problem : Will the following code compile and run?

int main() { int a = 5; a = *&*&*&*&a; printf("a is %d\n", a); return 0; }

Absolutely. Of course, the a = *&*&*&*&a; line is somewhat confusing. Let's break it down. a = *&a is taking the address of a, and then dereferencing that, which is then a again. So if *&a is equivalent to a, then *&*&a is equivalent to *&(*&a) which is equivalent to *&a which we already know to be valid. By this reasoning we know that the entire line is valid. Thus, this program will print out: a is 5

Problem : Will the following code compile and run?

int main() { int a = 5; a = **&&a; printf("a is %d\n", a); return 0; }

No. Let's break this one down. First, will the following work? a = *&a; Yes. &a is the address of a. The * operator goes to that memory address and gives back what sits there, in this case, a. However, &&a doesn't make any sense. This is saying, "give me the address of a, and then give me the address of that address". But the address of a doesn't have an address; it doesn't reside in memory. So this won't even compile.

Problem : Why do we care about assigning the value NULL to a pointer when the pointer isn't being used?

NULL is the only address that we can be sure none of our valid memory resides at. The computer sets aside a special address to be NULL. On most computers this is 0x0. Because nothing valid can ever be at that address, we can just store the value NULL into a pointer when we're not using it, and then later on we can check to see if the value is NULL. If it is, then it doesn't point to anything valid. If it isn't, then it does point to something valid. If we didn't have this special value NULL, then we would have no way of knowing whether the address contained in a pointer was valid or not, and we would have to try it to see. If we dereferenced an invalid pointer, our program would most likely crash.