I would expect that my normal array gives me the values. And the array that holds of pointers gives me the addresse of the values.
You put the same data into each array, so it's not surprising that you got the same data out of them. Specifically:
char *array[] = {'a','b','c','d'};
In this case, you created an array containing four values, and you told the compiler that those values are of type char *. But whatever their type, they're still the same values, 'a', 'b', and so on. You might as well have written:
char *array[] = {97, 98, 99, 100);
because that's exactly the same thing. Specifying the type of the contents of the array as char * doesn't make the compiler treat the values in the array differently -- it doesn't say "oh, I guess in this case I should take the addresses of those values instead of using the values themselves" just because the type is char *. If you want an array of pointers to some set of values, you'll need to get those pointers yourself using other means, such as the & operator, allocating space for each one, etc.
Note: In a comment below, M.M. points out that using values of type char to initialize an array of type char * isn't allowed by the C standard. In my experience, compilers typically warn about this kind of thing (you should've gotten several warnings like warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' when you compiled your code), but they'll still soldier on and compile the code. In summary: 1) Don't do that, and 2) different compilers may do different things in this situation.
I know that '[]' is used to dereference and get the value of the address the pointer is pointing at but it is also used to access array elements and the only reasonable explanation here is that it does both at the same time.
An array in C is a single contiguous piece of memory in which a number of values, all of the same type and size, are arranged one after another. The [] operator accesses individual values within the array by calculating an offset from the array's base address and using that to get the value. I think the thing that's confusing in your example is that you've created an array of char *, but with values that look like char. As far as the compiler is concerned, though, 'a' (a.k.a. 97, a.k.a. 0x61) is an acceptable value for a pointer to a character, and you could dereference that and get whatever character is stored at location 0x61. (In reality, doing that might cause an exception; the lowest region of memory is reserved on many machines.)