1

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
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
zyu leo
  • 19
  • 1

2 Answers2

2

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
$
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

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

abhiarora
  • 9,743
  • 5
  • 32
  • 57