Edit:
You're answer to A,B,C lies in this article i think:
Initializing Pointers
After a local pointer is declared but before it has been assigned a value, it contains an unknown value. (Global pointers are automatically initialized to null.) Should you try to use the pointer before giving it a valid value, you will probably crash your program—and possibly your computer’s operating system as well—a very nasty type of error!
There is an important convention that most C/C++ programmers follow when working with pointers: A pointer that does not currently point to a valid memory location is given the value null (which is zero). By convention, any pointer that is null implies that it points to nothing and should not be used. However, just because a pointer has a null value does not make it “safe.” The use of null is simply a convention that programmers follow. It is not a rule enforced by the C or C++ languages. For example, if you use a null pointer on the left side of an assignment statement, you still run the risk of crashing your program or operating system. Because a null pointer is assumed to be unused, you can use the null pointer to make many of your pointer routines easier to code and more efficient. For example, you could use a null pointer to mark the end of a pointer array. A routine that accesses that array knows that it has reached the end when it encounters the null value. The search() function shown here illustrates this type of approach.
/* look up a name */
int search(char *p[], char *name)
{
register int t;
for(t=0; p[t]; ++t)
if(!strcmp(p[t], name)) return t;
return -1; /* not found */
}
The for loop inside search() runs until either a match is found or a null pointer is encountered. Assuming the end of the array is marked with a null, the condition controlling the loop fails when it is reached.
C/C++ programmers commonly initialize strings. You saw an example of this in the syntax_error() function in the section “Arrays of Pointers.” Another variation on the initialization theme is the following type of string declaration:
char *p = “hello world”;
As you can see, the pointer p is not an array. The reason this sort of initialization works is because of the way the compiler operates. All C/C++ compilers create what is called a string table, which is used to store the string constants used by the program. Therefore, the preceding declaration statement places the address of hello world, as stored in the string table, into the pointer p. Throughout a program, p can be used like any other string. For example, the following program is perfectly valid:
#include
#include
char *p = “hello world”;
int main(void)
{
register int t;
/* print the string forward and backwards */
printf(p);
for(t=strlen(p)-1; t>-1; t–) printf(”%c”, p[t]);
return 0;
}
In Standard C++, the type of a string literal is technically const char *. But C++ provides an automatic conversion to char *. Thus, the preceding program is still valid. However, this automatic conversion is a deprecated feature, which means that you should not rely upon it for new code. For new programs, you should assume that string literals are constants and the declaration of p in the preceding program should be written like this.
const char *p = “hello world”;