I had written some code but it is giving me some strange result.
#include <stdio.h>
#include<string.h>
int main()
{
char r[]={"1dam"};
printf(" %s \n %s ",r,&r);
return(0);
}
output
1dam
1dam
I had written some code but it is giving me some strange result.
#include <stdio.h>
#include<string.h>
int main()
{
char r[]={"1dam"};
printf(" %s \n %s ",r,&r);
return(0);
}
output
1dam
1dam
The pointers have the same value (point to the same address) but have different types.
One (r
) is char *
, the other (&r
) is char (*)[5]
(pointer to array of 5 characters). A good compiler will warn you that %s
can't process char (*)[5]
. The address is the same, but add one to each and print the pointer value (%p
and cast to (void *)
) and you'll get different results.
#include <stdio.h>
int main(void)
{
char r[]={"1dam"};
printf("%s\n%s\n", r, &r);
printf("%p : %p\n", (void *)r, (void *)&r);
printf("%p : %p\n", (void *)(r + 1), (void *)(&r + 1));
return(0);
}
Output (on a Mac running macOS 10.13.6 High Sierra, using GCC 8.2.0):
1dam
1dam
0x7ffeebe8648b : 0x7ffeebe8648b
0x7ffeebe8648c : 0x7ffeebe86490
I had to compile suppressing my normal options, which gave:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pa31.c -o pa31
pa31.c: In function ‘main’:
pa31.c:6:22: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[5]’ [-Werror=format=]
printf("%s\n%s\n", r, &r);
~^ ~~
cc1: all warnings being treated as errors
$
The name of an array (in your case array r
) usually evaluates to the address of the first element of the array, so r
and &r
have the same value (but different types, so r + 1
and &r + 1
will not be equal if the array is more than 1 element long).
If your array has been defined as TYPE array[size]
, array name will decay to type TYPE *
. Any increments/decrements operation on such variable will result in pointer moving in steps of TYPE
bytes.
&r
evaluates to the same address, but given the same definition, it creates a pointer of the type TYPE (*)[size]
(pointer to an array of size TYPE) (refer this untangling complex declarations in C
) -- i.e., it's a pointer to an array, not to a single element. If you increment this pointer, it'll add the size of the entire array, not the size of a single element.
However, the same thing doesn't happen with a variable declared as pointer
to TYPE
(TYPE *ptr). You can run the program given below. In the program below, I have printed the addresses of r
, &r
, ptr
and &ptr
. You can see the address of r
and &r
is same (but they have different type). However, ptr
and &ptr
have different addresses (and they have different types as well. ptr
is of type char *
and &ptr
is of type char **
).
You can refer this question to understand the concept in detail.
For example, consider the program given below:
#include <stdio.h>
#include <string.h>
int main()
{
char r[] = "1dam";
printf(" %s \n %s \r\n",r, &r);
char *ptr = r;
printf( " Pointers: %p %p \r\n", ptr, &ptr);
printf( " Array: %p %p \r\n", r, &r);
return 0;
}
The output of the program is:
1dam
1dam
Pointers: 0x7fff4d46cd50 0x7fff4d46cd48
Array: 0x7fff4d46cd50 0x7fff4d46cd50
However, compiling the above code (on my Linux
machine) issues a warning.
test.c:7:9: warning: format ‘%s’ expects argument of type ‘char ’, but argument 3 has type ‘char ()[5]’ [-Wformat=] printf(" %s \n %s \r\n",r, &r);