Reputation: 493
In the code below, str
is a pointer that stores the address of the array Goodbye
. The address of array Goodbye
starts at 4196004
and the value of pointer *str2
is -1226226648
. My question is, is there a way to print address of array Goodbye
using the pointer *str2
?
I tried this line printf("%d %d %s\n", *str2, str2, str2);
that dereferences str2
and it prints 71
which is ascii for H
, but how would I print the address 4196004
int main(int argc, char **argv) {
char str1[] = "Hello";
char *str2 = "Goodbye";
printf("%d %d %s\n", &str1, str1, str1);
printf("%p %d %s\n", &str2, str2, str2);
}
Output:
-1226226640 -1226226640 Hello
-1226226648 4196004 Goodbye
Upvotes: 0
Views: 11144
Reputation: 311126
For starters you shall use correct conversion specifiers in the function printf
. Otherwise the behavior of the function is undefined.
So these calls
printf("%d %d %s\n", &str1, str1, str1);
printf("%p %d %s\n", &str2, str2, str2);
are wrong because there is used the conversion specifier %d
with pointers.
My question is, is there a way to print address of array Goodbye using the pointer *str2?
In fact the address of the array that corresponds to the string literal "Goodbye"
is the same as the address of the first character of the string literal.
char *str2 = "Goodbye";
However you can not obtain a pointer to the string literal using the pointer str2
.
What is the problem?
The pointer str2
knows nothing about whether it points to a single object of the type char
or to the first character of some array. It does not keep such an information.
Take into account that the array that corresponds to the string literal "Goodbye"
has type char[8]
. So a pointer that would point to the array shall have type char ( * )[8]
.
You could write for example
char ( *str2 )[8] = &"Goodbye";
In this case the pointer str2
indeed will have the address of the array. Otherwise having the pointer as it is defined in your example
char *str2 = "Goodbye";
you can not get the address of the array because as it was mentioned the pointer knows nothing about the array and its size.
On the other hand the value of the address of the first character of the string literal is equal to the value of a pointer to the string literal. That is if to consider the first declaration
char str1[] = "Hello";
then the expressions str1
and &str1
will yield the same value though the expressions have different types. The first one has the type char *
(if the expression is used in a context when an array designator is implicitly converted to pointer to its first element). And the second one has the type char ( * )[6]
. But the both values will be equal.:)
It is seem from the output (provided that you used correct conversion specifiers)
-1226226640 -1226226640 Hello
Upvotes: 0
Reputation: 727047
Start by fixing undefined behavior - cast your pointers to void*
, and use %p
to print them:
printf("%p %p %s\n", (void*)&str1, (void*)str1, str1);
printf("%p %p %s\n", (void*)&str2, (void*)str2, str2);
This produces the following output:
0x7ffe95676bf0 0x7ffe95676bf0 Hello
0x7ffe95676be8 0x2b4dca5eb7d4 Goodbye
Let's go through it to see why there is a difference between printing lines for str1
and str2
.
The reason is that str1
is an array, while str2
is a pointer. When you take a pointer to an array with operator &
you produce a pointer to array's initial element; when you convert an array to a pointer implicitly, you also get a pointer to array's initial element. Therefore, both printouts of %p
for &str1
and str1
produce the same value of 0x7ffe95676bf0
.
On the other hand, str2
is a pointer. It points to something (the string literal "Goodbye"
), but it also has an address of its own. When you print str2
without &
, you get the value of the pointer, i.e. the location of string literal "Goodbye"
. When you print &str2
, however, you get a pointer to pointer str2
, which is the location of str2
. This is different from the location of "Goodbye"
, so the printout is different.
If you start with the address of str2
, i.e.
char *str2 = "Goodbye";
char **ptrStr2 = &str2;
you can get the location of "Goodbye"
by dereferencing, i.e.
printf("%p %s\n", (void*)*ptrStr2, *ptrStr2);
Upvotes: 0
Reputation: 35164
Concerning str2
we can distinguish "the address to which pointer str2
points to", which is the address where string literal Goodbye
will reside (e.g. 0x10007bf04
) from "the address at which pointer str2
is stored", which is the address of the variable (e.g. 0x7fff5fbff710
) in which the address value 0x10007bf04
is stored.
int main(int argc, char **argv) {
char str1[] = "Hello";
char *str2 = "Goodbye";
printf("%p %p %s\n", (void*)&str1[0], (void*)str1, str1);
printf("%p %p %s\n", (void*)&str2, (void*)str2, str2);
}
In contrast to pointers, *str2
denotes a character value as it dereferences pointer str2
. Getting the "address of *str2" would then be the address of the first character of the string literal to which str2
points to. You could write this as &(*str2)
or &str2[0]
, but both translate to str2
.
Note that printing a pointer using format "%d"
invokes undefined behaviour.
Upvotes: 0
Reputation: 73444
Your code invokes Undefined Behavior, since you try to print addresses without using %p
printf()
mentions:
p
Pointer address
and don't cast to void
, as you ought to.
So, do it like this instead:
printf("%p %p %s\n", (void*)&str1, (void*)str1, str1);
printf("%p %p %s\n", (void*)&str2, (void*)str2, str2);
Possible output:
0x7ffddaf7e67a 0x7ffddaf7e67a Hello
0x7ffddaf7e670 0x4005c4 Goodbye
Upvotes: 1