artic sol
artic sol

Reputation: 493

c printing address of an array pointed to by a pointer

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

Answers (4)

Vlad from Moscow
Vlad from Moscow

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

Sergey Kalinichenko
Sergey Kalinichenko

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);

Demo.

Upvotes: 0

Stephan Lechner
Stephan Lechner

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

gsamaras
gsamaras

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

Related Questions