Reputation: 101
int main(){
char *str1="Hi", *str2 = "Bye";
printf("%u,%u\n",&str1,str1);
int arr[5]={1,2,3,4,5};
printf("%u,%u",arr,&arr);
}
What is happening here? str
and &str
give different addresses and arr
and &arr
give same.
My understanding is that arr
points to address of first element i.e &arr[0]
and &arr
will give also the same address but it is address of whole arr[5]
. If we increment &arr
by 1 then it will point to next element of arr[4]. But problem is that why this process is different in case of string. Please help me to visualize the concept here.
Upvotes: 2
Views: 1477
Reputation: 67476
array
is not a pointer. It is contiguous chunk of memory. That the reason why array
&& &array
have the same address.
pointer
is a variable holding the reference to another variable. So the pointer
gives you the reference/address held by the pointer and &pointer
gives you the reference/address to the pointer
itself. As the pointer is a separate 'object' you have different addresses.
Upvotes: 1
Reputation: 310950
In this declaration
char *str1="Hi", *str2 = "Bye";
there are declared two local variables str1
and str2
with the automatic storage duration.
They are initialized by addresses of first characters of string literals that have the static storage duration.
So the value of str1
is the address of the first character of the string literal "Hi"
. The value of the expression &str1
is the address of the local variable str1
itself.
You can imagine it the following way
&str1 ---> str1 ---> "Hi"
Arrays are contiguous extents of memory. So the address of an array itself and the address of its first element are the same. It is the address of the extent of memory occupied by the array.
You can imagine it the following way
| 1 | 2 | 3 | 4 | 5 |
^
|
&arr----
^
|
arr-----
Pay attention to that array designators used in expressions with rare exceptions are converted to pointers to their firs elements. So use din the call of printf the expression arr
is equivalent to &arr[0]
.
Regarding to your comment
Vlad I've a doubt regard string constant, Why can't we modify this char *s="HI" but we can modify this char *s[]="HI" I know about second case it is simple array but can you please clear why can't i modify string constant
then according to the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
Pay attention to this declaration
char *s[]="HI";
is invalid. There is declared an array of pointers. So to initialize it you have to write
char * s[] = { "HI" };
And you may change the elements of the array by assigning to them other string literals. That is you may change pointers themselves not the string literals pointed to by the pointers.
Upvotes: 1
Reputation: 15032
char *str1="Hi";
printf("%u,%u\n",&str1,str1);
First you use the wrong conversion specifier, %u
for both, str1
and &str1
, which invokes undefined behavior. For str1
it shall be %s
and for &str1
it shall be %p
:
char *str1="Hi";
printf("%p,%s\n",(void*) &str1, str1);
Explanation:
str1
is a pointer to the address of the first element of the string literal "Hi"
. &str1
is the address of the pointer str1
itself. That is the difference to the version with the array below.
int arr[5]={1,2,3,4,5};
printf("%u,%u",arr,&arr);
Again, the wrong conversion specifiers here. It shall be %d
or %i
if you want to print the first element of arr
as arr
is an array of int
not unsigned int
or %p
if you want to print the address of the first element:
int arr[5]={1,2,3,4,5};
printf("%p,%p",(void*) arr, (void*) &arr);
Explanation:
arr
(after array-to-pointer decay rule) decays to a pointer to the first element of arr
while &arr
is actually a pointer to the first element of arr
. They actually evaluate to the same.
Note, the cast to void*
is necessary to make the code C standard-compliant.
Upvotes: 1
Reputation: 409166
In C all string literals are really stored as arrays of (read-only) characters including a null-terminator. As any other array they decay to a pointer to their first element.
For str1
in your code the compiler have generated some code similar to this:
// Compiler-generated array for the string
char global_array_for_Hi[] = { 'H', 'i', '\0' };
int main(void)
{
char *str1 = global_array_for_Hi;
...
}
Your pointer variable str1
is pointing to the first element (the 'H'
) of this array. When you print the value of str1
that's the value you get.
When you print the value of &str1
you get the location of the variable str1
itself, you get a pointer to str1
of the type char **
.
Somewhat graphically it could be seen like
+-------+ +------+ +-----+-----+------+ | &str1 | --> | str1 | --> | 'H' | 'i' | '\0' | +-------+ +------+ +-----+-----+------+
For arr
you have an array, it decays to a pointer to its first element. When you use arr
it's the same as &arr[0]
(it comes from the fact that arr[i]
is exactly equal to *(arr + i)
). The type of arr
(and &arr[0]
) is int *
.
When you use &arr
you get a pointer to the whole array, and its type is int (*)[5]
.
The location is same for both &arr[0]
and &arr
, but their types are very different.
On a related note, the printf
format specifier %u
is for printing values of the type unsigned int
. To print pointers (more specifically values of type void *
) you must use the format specifier %p
. Mismatching format specifier and argument type leads to undefined behavior.
Upvotes: 7
Reputation: 123
In C, constant string like "Hi, Guys" is stored on shared memory. Consider following example:
str = "Hi, there";
The string in above code is stored contiguously. The variable str
points to
first character of string, So character 'H' here.
So, str
gives address of first character which stored on somewhere in memory.
&str
gives address of variable str
itself.
The case in array is different than above.
Array is variable(off course, const variable) that contains address of first element(that is &arr[0]) of array. And when you do &arr
it will same as &arr[0]
. &arr is actually address of whole array which is same as address of first element of array.
Note: print &arr + 5
and &arr[0] +5
, you may got some light.
Upvotes: 1