5

How can you interpret the following line of code?

int (*arrayABC)[10];

In my textbook, it says that we have a pointer to a pointer to the 0th element of an integer array.

However, I don't quite understand this.

My interpretation: We have some variable, which gets as its value some address. This address is then the address of the 0th element of an UNNAMED integer array. Basically we have a pointer to the 0th element.

Why then to have a pointer TO A POINTER?

Kevin Wu
  • 1,357
  • 1
  • 15
  • 34
  • Admittedly it wouldn't have been enough to answer your question, but when you are having trouble with a C declaration, [Cdecl](http://cdecl.org/) is always a good starting point. What textbook is it, anyway? – Fabio says Reinstate Monica Jan 04 '17 at 22:00
  • Note that it is sometimes good and useful to have a pointer to a pointer. As the answers explain, however, that's not what you have in your example. – John Bollinger Jan 04 '17 at 22:03
  • @FabioTurati The link can be tailored. Example [arrayABC as pointer to array 10 of int](http://cdecl.org/?q=int+%28*arrayABC%29%5B10%5D%3B) – chux - Reinstate Monica Jan 04 '17 at 22:20
  • 1
    Could you perhaps leave a note about which book you are reading and post the exact quote? So we can blacklist the book and shame the author publicly on the internet. – Lundin Jan 05 '17 at 07:53

3 Answers3

14

This is a pointer to an array. It is not a pointer to a pointer. Arrays and pointers are different. An array has an address, but an array is not an address. An array is a series of contiguous elements.

This pointer points to the whole array and not just the first element, in the same way that a float * points to the whole float and not just the first byte.

If you have for example:

int foo[10];
int (*arrayABC)[10] = &foo;

then the expressions (*arrayABC) and foo are identical. E.g. foo[3] is the same as (*arrayABC)[3].

M.M
  • 138,810
  • 21
  • 208
  • 365
  • So basically this expression is the same as int arrayABC[10] with the exception that we can do something like arrayABC++? – Kevin Wu Jan 04 '17 at 22:05
  • @KevinWu no it is not much like that. The difference between `int x[10];` and `int (*x)[10];` is the same as the difference between `float y;` and `float *y;` – M.M Jan 04 '17 at 22:06
  • What happens then if I dereference? (Do *arrayABC) – Kevin Wu Jan 04 '17 at 22:08
  • @KevinWu added that to my answer. You can use `(*arrayABC)` in exactly the same way and with the same behaviour as you would use the name of the array that it points to. – M.M Jan 04 '17 at 22:21
  • @M.M Is `(*arrayABC)` the only way to access it as array? Can I dereference and store it into a variable first so I don't have to dereference it everytime? – raymai97 Jan 05 '17 at 01:18
  • @raymai97 I'm not sure what you mean. A pointer points to things, the purpose of using a pointer is so that you can dereference it to access the thing it is pointing to. If you don't want to dereference every time then don't use a pointer. You could make another array that is a copy of the array being pointed to. – M.M Jan 05 '17 at 02:00
  • @M.M Let's say we have `int a = 30, b = 0;`, then `int *p = &a;`, I can deference the value into `b` by doing `b = *p;`, which will copy the value pointed by `p` into `b`. I would like to know if it's possible to deference `(*arrayABC)` into an array variable, making a copy of array. – raymai97 Jan 05 '17 at 02:36
  • 1
    @raymai97 yes, write `int b[10]; memcpy(b, *arrayABC, sizeof b);` . The assignment operator does not work with arrays in C, you have to use `memcpy` or a loop assigning element by element. – M.M Jan 05 '17 at 03:00
  • Two Questions: 1. Will foo upon use not decay into a pointer to the first element of the array and thus &foo actually give back the address of the pointer? 2. When we say that a variable points to an array, what address is actually stored in it? How does it work internally? – Kevin Wu Jan 07 '17 at 19:37
  • @KevinWu 1. no, please look up the decay rule. It does not happen in the case `&foo`. The temporary pointer that results from decay does not have an address anyway. 2. The meaning is exactly the same as pointing to a `float` or anything else. "how does it work internally" is an implementation detail, you could experiment with your compiler if you want, but the most common implementation is that at runtime the pointer holds a number corresponding to the memory address of the first byte of the object being pointed to – M.M Jan 07 '17 at 22:38
  • but then what is the difference to a pointer pointing to the first element/byte of the array? – Kevin Wu Jan 11 '17 at 08:36
  • @KevinWu the same as the difference between a pointer to float, and a pointer to char which points to the first byte of the float. pointers have a type that they point to – M.M Jan 11 '17 at 10:57
3

If you have an object of a type T then a pointer to the object is declared like

T obj;

T *ptr = &obj;

Now let's the type T is defined the following way

typedef int T[10];

Thus the code above

T obj;

T *ptr = &obj;

can be rewritten using the typedef definition like

int obj[10];

int (*ptr)[10] = &obj;

In the both cases, when T is some abstract type and when T is an alias for int[10], ptr is a pointer to an object. In the last case ptr is a pointer to an array of 10 elements of type int. That is the object pointed to by ptr has array type. Arrays and poiters are different types.

Try the following simple demonstrative program

#include <stdio.h>

int main( void )
{
    typedef int T[10];

    T a;

    T *pa = &a;

    printf( "%zu\n", sizeof( *pa ) );

    int b[10];

    int ( *pb )[10] = &b;

    printf( "%zu\n", sizeof( *pb ) );
}    

Its output is

40
40

As you can see the both values are equal to the size of an integer array of 10 elements. So the pointers point to arrays.

If you write

int *arrayABC[10];

you will get an array of 10 pointers of type int *.

If you write

int (*arrayABC)[10];

you will get a pointer to an array of 10 integers.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

In my textbook, it says that we have a pointer to a pointer to the 0th element of an integer array.

Your textbook is ... badly worded, let's leave it at that. It's a pointer to a 10-element array of int.

I can kind of see where the book is coming from. Given the declaration

int (*a)[10];

the expression *a will have type int [10] (10-element array of int). However, unless that expression is the operand of the sizeof or unary & operators, it will be converted ("decay") from type int [10] to int *, and the value of the expression will be the address of the first element of the array:

Expression       Type        "Decays" to        Value
----------       ----        -----------        -----
        *a       int [10]    int *              Address of first element of the array;
                                                equivalent to `&(*a)[0]`.  

Thus, if I call a function like

foo( *a );

what the function actually receives will be a pointer to the first element of the pointed-to array (its type will be int *, not int **).

So in effect, yes, a often winds up behaving as a pointer to a pointer to the first element of the array; however, its type is not "pointer to pointer to int", and type matters. Given:

int (*a)[10];
int **b;

then you'll get different behavior for the following:

sizeof *a vs. sizeof *b
a + i vs b + i (also applies to a++ vs b++)
John Bode
  • 119,563
  • 19
  • 122
  • 198