1

I mean, why does this print equal numbers to the console?

#include <stdio.h>
int main()
{
    char localarr[99];
    printf("%d\n",(int)localarr);
    printf("%d\n",(int)&localarr);
    return 0;
}

I understand that the address of localarr is not actually stored in any variable. But the generated code could store that behind the scenes, or at least gcc could give warning instead of allowing for segfault when I pass such to a function that expects char**. Why do we have this behaviour?

Related: why does

char **ppl = &localarr;

results in:

error: cannot convert ‘char (*)[99]’ to ‘char**’

?

user1358
  • 623
  • 2
  • 8
  • 13

3 Answers3

5

No, localarr is not same as &localarr

  • localarr is address of first element but &localarr is address of array of chars of size 99. off-course values are same but both are different semantically.

  • localarr is of type char [99] whereas &localarr is of type char (*)[99]

And because type of &localarr is char(*)[99] you should create pointer to array, like:

char(*ppl)[99] = &localarr; 

where ppl is ponter to array of chars of size 99

To visualize difference between localarr and &localarr below is my diagram:

    +----+----+----+---+---+----+----+----+----+----+ 
    | '1'| '2' |'3'|...............  |98  | 99 |  ...........
    +----+----+----+---+---+----+----+----+----+---+----+  
     201   202  203 ...............   210  299
      ^     ^                                         
      |     |                                         
 (localarr) (localarr + 1)                                         
    |                                         |
    |-----------------------------------------|--------
    |201                                      | 299    // 299 -201 = 98
      ^                                          ^
      |                                          |
    (&localarr)                                 (&localarr + 1)      

(Note:)
* localarr + 1 increment by one char size, where as (&localarr + 1) increment by 99 array size.

have a look on this code and its output:

int main()
{
    char localarr[99] = {'A'};
    printf("%p %p\n",localarr, &localarr);
    printf("%p %p\n",(localarr + 1), (&localarr + 1));
    printf("%c %p  %c\n",*localarr, *&localarr, **&localarr);
        return 0;
}

Output:(read comments)

~$ ./a.out 
0x7fff41ad64b0 0x7fff41ad64b0    // same 
0x7fff41ad64b1 0x7fff41ad6513    // difference is 98, 4b1 + 62 = 513
A      0x7fff41ad64b0  A

Note: value of localarr and &localarr are same that is 0x7fff41ad64b0 But values of *localarr and *&localarr are not same:

  • *localarr is first element

  • *&localarr is address of first element **&localarr is first element

  • that means *localarr is same as **&localarr that is first element localarr[0]

  • Note 0x7fff41ad6513 - 0x7fff41ad64b1 = 0x62 and 0x62 = 98 in decimal

What compiler error message is:

error: cannot convert ‘char (*)[99]’ to ‘char**’ 
                       ^                  ^ type of ppl  
                  type of &localarr 

Read this Issue with pointer to character array

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • Although I accepted the answer, I must note that all answers (even for other similar questions) only explain WHAT happens, but NOT WHY it happens. So why is the semantics of C such? It would be less error-prone to just raise a compiler-error and enforce casting. Or not? – user1358 Apr 06 '13 at 12:59
  • @user1358 C is comparatively low language then other. As I says both are different in types and semantic compiler produces an error. If you compiles with proper option it will produce an warning to. – Grijesh Chauhan Apr 06 '13 at 13:10
1

Given:

#include <stdio.h>
int main()
{
    char localarr[99];
    printf("%d\n",(int)localarr);
    printf("%d\n",(int)&localarr);
    return 0;
}

The type of localarr is array of 99 char. The type of &localarr is pointer to an array of 99 char. The types are different. However, localarr degenerates to a pointer to the first byte of the array. You can spot the difference most clearly by adding 1 to the addresses (and converting the code to handle the types more reliably — on a 64-bit system, the cast to int truncates the pointer):

#include <inttypes.h>
#include <stdio.h>

int main(void)
{
    char localarr[99];
    printf("0x%08" PRIXPTR "\n", (uintptr_t)( localarr+0));
    printf("0x%08" PRIXPTR "\n", (uintptr_t)(&localarr+0));
    printf("0x%08" PRIXPTR "\n", (uintptr_t)( localarr+1));
    printf("0x%08" PRIXPTR "\n", (uintptr_t)(&localarr+1));
    return 0;
}

Example output:

0x7FFF6D12C4E0
0x7FFF6D12C4E0
0x7FFF6D12C4E1
0x7FFF6D12C543

You also ask:

Why does

 char **ppl = &localarr;

result in the error cannot convert 'char (*)[99]' to 'char**'?

As already stated, the type of &localarr is a pointer to an array of 99 char; this type is neither the same as nor convertible to char **, which in many ways simply echoes what the error message says. The types are just completely incompatible.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

your statement will work if u use

char *localarr=calloc(99,sizeof(char));

now assigning the address of localarr to a char ** type should work

Darshan Shah
  • 57
  • 1
  • 7