Let me explain. Let’s assume you’ve declared an array of chars (C’s version of a string) called str1 and a pointer to an array of chars, str2:
char str1[] = "Hello";
char *str2 = "Goodbye";
An array and an address (in C) are equivalent. So str1 is the address at which the array of characters in the string "Hello" are stored. But str2 is a pointer whose value is the address of the string "Goodbye".
In fact, str1 isn’t a variable because its value (the address of an array) cannot be changed. The contents of the array – its individual elements – can be changed. The address of the array, however, cannot. That is why I prefer to call str1 an array ‘identifier’, though many people would call it, somewhat inaccurately, an ‘array variable’.
But, wait a moment. If the value of an array identifier such as char str1[] and the value of a pointer variable such as char *str2 are both addresses, aren’t str1 and str2 both pointers?
No, they are not.
It is an essential feature of a variable that its value can be changed. The value of an array identifier cannot be changed. What’s more, a pointer variable occupies one address; its value can be set to point to different addresses. But an array identifier and its address are one and the same thing. How can that be?
You have to understand what happens during compilation. When your program is compiled, the array identifier, str1, is replaced by the address of the array. That address cannot be changed when your program is run. But str2 is a pointer variable with its own address. Its value (the address of an array) can change if new addresses are assigned to the pointer variable.
If you need to know more about the mysteries of pointers, arrays and addresses in C, I have a book that explains everything (with all the source code examples for you to download). It’s called The Little Book Of Pointers and it’s available as a paperback or eBook from Amazon (US), from Amazon (UK) and other Amazon stores worldwide.