Reputation: 5938
This is probably a beginner question but it has been confusing me. I understand that in c an array is itself a pointer to the first element of the array. So consider the following example
char *words[LENGTH];
words[0] = "zero";
words[1] = "one";
words[2] = "two";
printf("%s\n",*words);
What ends up printing is zero
. However, my understanding is that words
is a pointer to the first element of the words
array which is a char pointer => words
is a pointer to a pointer to a char. Therefore *words
would be a pointer to char. Therefore I would expect a memory address to be printed here and not an actual string. What am I misunderstanding here?
Upvotes: 0
Views: 177
Reputation: 673
The context in which *
(not *
as in multiplication) matters,
when used in declearation as in char *words[LENGTH]
word becomes array of pointers to char.
as far as pointers are concern *
is Value at address operator, it gives Value stored at particular address, while &
is the address operator, gives address of variable.
printf("%s\n",*words) // prints value at address to which word points
while
printf("%p\n",words) // prints address to which word points
Upvotes: 1
Reputation: 123448
I understand that in c an array is itself a pointer to the first element of the array.
This is not correct - under most circumstances, an expression of type "N-element array of T
" will be converted to an expression of type "pointer to T
", but an array object itself is not a pointer. No storage is set aside for a pointer as part of an array object.
The string literal "zero"
has type "5-element array of char
", while both "one"
and "two"
have types "4-element array of char
" (because strings are terminated with a zero-valued character, you need N+1 elements to store an N-character string).
Each string literal is an array expression, but since these expressions are not operands of the sizeof
or unary &
operators, and since they arent being used to initialize a character array, each expression is converted to a pointer expression, and the value of each expression is the address of the first element of the array.
Therefore I would expect a memory address to be printed here and not an actual string. What am I misunderstanding here?
The %s
conversion specifer tells printf
to print the sequence of characters beginning at the specified address until it sees a string terminator - that's why you see zero
as the output and not an address. To print a pointer value, you'd use the %p
conversion specifier like so:
printf( "%p\n", (void *) *words );
Upvotes: 3
Reputation: 99
As @Stargateur replied you need to both use the %p flag and use the (void *). Please note that it will show you the starting address of the first string ('zero') and the next code will go over all the strings and print their address (think of the 3 strings as a 2D (two dimensions) strings array having different lengths.
#include <stdio.h>
#define LENGTH 3
int main(void)
{
char *words[LENGTH];
words[0] = "zero";
words[1] = "one";
words[2] = "two";
int len = 0;
while(len<(int)LENGTH)
{
printf("%s\n", words[len]);
printf("%p\n", (void *)words[len]);
len++;
}
printf("\n%p\n", (void *)*words); // prints the first address only (the 'zero' address)
return 0;
}
Upvotes: 2
Reputation: 351
char *words[LENGTH];
defines an array of char*, i.e. char**. *words
equals to words[0]
which refers to "zero".
It is not safe to create such char* array. For example, the following code compiles OK, but its behavior is undefined.
char *words[1];
words[0] = "zero";
words[1] = "one";
words[2] = "two";
printf("%s\n", words[2]);
Upvotes: 1
Reputation: 397
Your understanding of what you have done up to the printf is spot on - as you've written it, *words
is in fact a pointer to a char. The %s
format specifier is for printing strings, so it assumes that whatever pointer you pass it is actually an array of chars that ends with a '\0'
char - the format c uses for storing strings. With that information, printf knows that it should just print all of the characters in the array until it finds that '\0'
- which is exactly what it has done in this case. If you do want to print the address of that pointer, the correct format specifier is (as mentioned in Stargateur's answer) %p
.
Upvotes: 2
Reputation: 26717
You are close in fact you are right, c-string are a pointer that contain the address of the first char of the string. The c-string is not the bytes but the address. And printf flag %s
expect the address of these bytes. So you indeed give an address to printf()
but you ask to printf()
to show the value of the c-string. So "zero". Your only error is that you didn't read the manual of printf()
.
If you want the address try:
printf("%p\n", (void *)*words);
Upvotes: 1