Sanjay Verma
Sanjay Verma

Reputation: 101

Address of a string literal and array

    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

Answers (5)

0___________
0___________

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

Vlad from Moscow
Vlad from Moscow

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

1.

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.


2.

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

Some programmer dude
Some programmer dude

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

ravivasani75
ravivasani75

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

Related Questions