0

I have a basic doubt, when we de-reference a pointer to an array why we get name of the array instead the value of first member of an array, I see this has been asked here but I didn't get it exactly how?

dereferencing pointer to integer array


main()
{
    int var[10] = {1,2,3,4,5,6,7,8,9,10};
    int (*ptr) [10] = &var;

    printf("value = %u %u\n",*ptr,ptr);  //both print 2359104. Shouldn't *ptr print 1?


}

So, is it like when we dereference a pointer, it cancel out the reference operator and what we get is variable name, and in case of pointer to an array, it is the array name ?

main()
{
   int a = 10;
   int *p = &a;

   printf("%d\n", *p) /* p = &a; *p = *(&a); and having a dereference cancel out the &, gives us *p = a ? */
}
Milan
  • 1,447
  • 5
  • 19
  • 27
  • 1
    Try print out **ptr, this should give you the element (1) rather than the address. It just happens that the address of ptr (the pointer to arrays) is the same as the address of the first array in the pointer. – MMZK1526 Aug 10 '22 at 13:22
  • 1
    As an aside, [use `%p` for printing a pointer](//en.cppreference.com/w/c/io/fprintf), your current code is broken though it seems to "work" for you. – Deduplicator Aug 10 '22 at 13:35
  • Milan, `Shouldn't *ptr print 1` --> `ptr` is a pointer to an array. `*ptr` is an array. An _array_ is not an `int` 1. – chux - Reinstate Monica Aug 10 '22 at 14:25
  • @chux-ReinstateMonica, I am just confused how *ptr is decoded to an array, I understand ptr is a pointer to an array. how *(&a) gives an array instead of value 1. At address &a value stored is 1. – Milan Aug 10 '22 at 14:36
  • @Milan At address &a value stored is also the array (40 bytes long). – chux - Reinstate Monica Aug 10 '22 at 14:38
  • and that is what I failed to understand, how :( – Milan Aug 10 '22 at 14:43
  • @Milan Consider another case. If `b` was a pointer to a _widget_, would you expect `*b` to be a _widget_ or an `int`? – chux - Reinstate Monica Aug 10 '22 at 14:47
  • it should be an integer value. – Milan Aug 10 '22 at 14:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/247182/discussion-between-milan-and-chux-reinstate-monica). – Milan Aug 10 '22 at 15:12

2 Answers2

3

Because ptr has type int (*)[10] which is a pointer to an array, *ptr has type int[10] which is an array type.

This array decays to a pointer to its first element when it is passed to printf which then prints the pointer value. The result would be the same if you passed var to printf instead of *ptr.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • dbush, if *ptr has type int[10] then *ptr+1 should point to next 1-D array .i.e. *ptr + 40 ? – Milan Aug 10 '22 at 16:07
  • @Milan No, that would be `ptr + 1`. With `*ptr + 1`, first you have `*ptr` which has array type, then that array decays to a pointer to the first member, then adding 1 results in a pointer to the second member of the array. – dbush Aug 10 '22 at 16:10
  • okay, one more follow up question, int a[10], here a is an array of type int[10]. This is how one should read this ? – Milan Aug 10 '22 at 16:16
1

You do not get a variable name when you dereference a pointer. If the pointer points to an object the you get that object. If it does not point to an object then you get undefined behavior. In particular, if the pointer points to a whole array, then you get that array. That's a fundamental aspect of how pointers work.

However, a fundamental aspect of how arrays work is that in most contexts, an expression of array type is automatically converted to a pointer to the first array element. This address corresponds to the address of the array itself, but has different type (int * in your case, as opposed to int (*)[10]). Typically, converting these to an integer type produces the same value. Thus, in your example code, *ptr is equivalent to var, and each is automatically converted to a pointer of type int *, equivalent to &var[0].

But note also that it is not safe to convert pointers to integers by associating them with printf directives, such as %u, that expect a corresponding integer argument. The behavior is undefined, and in practice, surprising or confusing results can sometimes be observed. One prints a pointer value with printf by using a %p directive, and converting the pointer value to type void *. Example:

    printf("pointer = %p %p\n", (void *)*ptr, (void *)ptr);

Combined with the type and value of ptr from your example, this can be expected to reliably print two copies of the same hexadecimal number.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157