Указатели содержат адрес, не более того. Иногда вы обращаетесь к указателям для получения данных, в других случаях вы передаете указатель к коду, который будет разыменовывать его.
Например:
p1 = 0; //Point to invalid memory address, but an address nonetheless
p1 = str1 //Point to a valid buffer. p1 now holds an new address, nothing else
if(*p1 == 'A') //Dereference the pointer (gives a character)
printf("The first character in str1 is A.\n");
Вы можете подчеркнуть тот факт, что p1 не содержит данных, кроме указателя, реорганизовав вашу программу следующим образом:
char str1[80];
char *p1;
p1 = str1; //Point to un-initialized memory, your compiler might complain.
//but p1 is happy. It holds an address, it will never "hold" anything else.
//*p1 is valid (will not crash) but holds random garbage, do not use it!
cout <<"Enter a string"<<endl;
cin >> str1; //Now str1 was initialized
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("The first character in str1 is A.\n");
Теперь, чтобы подчеркнуть тот факт, что p1 и str1 - это одно и то же (один и тот же адрес в памяти), добавьте это в программу:
str1[0] = 'A'; //Put a capital A in str1
if(*p1 == 'A') //Dereference the pointer (it is now a character)
printf("Now that we forced an A, this test is always true.\n");