-1

Suppose we have that the following 2-dimensional array:

int multi[3][3];

As I understand it, we can then say that multi is a "pointer to a pointer", or -- at the very least -- we can do something like the followiong:

int **p_p_int = multi;

Question: Why don't we say that multi is a "pointer to a pointer to a pointer to pointer", since multi points towards the address of its first element, which itself points to a pointer, which points towards the address of multi[0][0], which itself points to the value of multi[0][0].

This seems to be 4 objects that point (here I'm counting addresses as pointers).

Now you might say "but addresses aren't pointers, even though pointers can equal addresses", in which case it also seems weird to say that a 2-dimensional array is a "pointer to a pointer", since it's actually a pointer to an address to a pointer to an address (to a value).

I feel like I have mananaged to confuse myself quite a bit here :)

George
  • 6,927
  • 4
  • 34
  • 67
  • `int multi[3][3];` decayes to `int* [3]`, that's all . – David Haim Feb 04 '16 at 17:33
  • 2
    Just because you can say it, doesn't make it true. – Benjamin Lindley Feb 04 '16 at 17:33
  • @BenjaminLindley what's wrong with that? – David Haim Feb 04 '16 at 17:34
  • 1
    @DavidHaim: What's wrong with the statement *"we can then say that multi is a "pointer to a pointer""* ? It's false, namely. – Benjamin Lindley Feb 04 '16 at 17:35
  • oh, I thought you talked about my statement,which may be false, I don't know anymore :) – David Haim Feb 04 '16 at 17:35
  • @George: Did you actually try this?: `int **p_p_int = multi;` – Benjamin Lindley Feb 04 '16 at 17:39
  • 1
    related/dupe: [Why can't we use double pointer to represent two dimensional arrays?](http://stackoverflow.com/questions/4470950/why-cant-we-use-double-pointer-to-represent-two-dimensional-arrays) – NathanOliver Feb 04 '16 at 17:46
  • @George try something line `printf("%p\n%p", multi, &multi[0][0]);` if you want evidence beyond the documentation that `multi` really isn't an array of pointers to other arrays. – Tommy Feb 04 '16 at 18:24
  • 1
    A 2D array is simply an array of arrays. Defining `int multi[3][3]` does not create any pointer objects, just an array consisting of 3 sub-arrays, each of which consists of 3 `int` objects. Evaluating the name `multi` can give you an *address* (a pointer value), but does not create a pointer object. An `int**` (pointer to pointer to `int`) cannot be used unless there is an `int*` pointer object for it to point to. Recommended reading: section 6 of the [comp.lang.c FAQ](http://www.c-faq.com/) (it applies to C++ as well as to C). – Keith Thompson Feb 04 '16 at 19:57

4 Answers4

2

A 1d array converts to a pointer rather than being one — e.g. you can reassign a pointer, you cannot reassign an array.

A literal 2d array isn't stored in the way described below.

However a 2d array can be achieved by a pointer to a pointer if:

int **array2d is a pointer. It points to an array. That array contains pointers.

Because array2d points to an array of pointers, array2d[n] is also a pointer. But it's a pointer to an array of integers.

So that's two pointers, total.

In pseudo code, the steps to look up the item at (m, n) are:

  • add m to array2d to index that array. Read pointer, p from calculated address;
  • add n to p to index that array. Read integer from calculated address.
Tommy
  • 99,986
  • 12
  • 185
  • 204
  • I think you are confusing `int *multi[]` (an array of `int*`) with `int multi[3][]` (an array of `int[3]`). In both cases, `multi[x][y]` is an `int`, but everything else is different. The second one really is a literal 2d array. – rici Feb 04 '16 at 17:51
  • I think all that's confusing is that I've reused `multi` as my variable name. I think I've otherwise been explicit as to why a 2d array can be stored via a pointer-to-pointer but that that's not what built-in 2d arrays are. – Tommy Feb 04 '16 at 17:57
  • What is `array2d`? `multi` is an array, but it contains no pointers. – Keith Thompson Feb 04 '16 at 18:00
  • @Tommy: `int multi[3][3]` *is* a 2d array. I'm not sure what you mean by "built-in 2d arrays", and your answer definitely doesn't make that clear. – rici Feb 04 '16 at 18:01
  • @rici I'm sorry that "a literal 2d array isn't stored that way but a 2d array can be achieved by a pointer to a pointer in that: ..." is insufficiently clear for you to warrant a comment. I don't think it would be problematic for most as distinguishing that: (i) a literal 2d array is stored in some way that I'm not going to discuss; but (ii) the reason you've heard that a pointer to a pointer can be used to hold a 2d array is that you could elect to lay things out as follows. Even if they (undesirably) had to parse the sentence twice due to its backwards, unhelpful structure. – Tommy Feb 04 '16 at 18:19
  • ... and I appreciate that the answer doesn't mention the fairly vague concept raised by my previous comment of "built-in 2d arrays"; that's an issue with the comment rather than the answer. I don't think it's worth addressing other than to concede that the comment isn't well-formed. – Tommy Feb 04 '16 at 18:22
  • @tommy: OK, I'll yield. I don't think you've really explained to OP what is really going on, nor have you addressed directly the question, but others have, so I don't think it matters too much. There's also a zillion duplicates, and possibly one of them actually explains C arrays properly. – rici Feb 04 '16 at 19:16
  • The question was about an actual 2D array, which is simply an array of arrays. Your answer goes off on a tangent about another way to achieve the effect of a 2D array using a different data structure. Your answer, after you edited it, is not incorrect (though you don't discuss memory allocation), but I don't believe it answers the OP's question about `int multi[3][3];`. – Keith Thompson Feb 04 '16 at 19:24
  • The question further queries why one might refer to the arrangement that he thinks a 2d array is using as merely a pointer to a pointer and not a pointer to a pointer to a pointer to a pointer. This answer applies that part of the question. As I understand it, on StackOverflow it is appropriate to post something as an answer if it contributes towards any part of the question asked, and the two people who voted upwards presumably agree. – Tommy Feb 04 '16 at 19:28
2

The job of a pointer is to point towards something. Just because something is both a pointer and points to something else doesn't make it a pointer to a pointer, unless that something else is a pointer.

So let's break this down:

multi points towards the address of its first element,

That makes it a pointer

which itself points to a pointer,

That makes it a pointer to a pointer.

which points towards the address of multi[0][0],

No. It contains the address of multi[0][0], it doesn't point to it.

which itself points to the value of multi[0][0]

Well, of course. It's a pointer, pointers point to values, that's their job. That doesn't make them pointers to pointers, it makes them pointers to values.

This seems to be 4 objects that point (here I'm counting addresses as pointers).

Sure, but two of those pointings are the very same pointing just counted twice. You say X is a pointer that contains a value that points to something as if that was two separate pointings. The job of a pointer is to have a value that points to something, that's what makes it a pointer in the first place. It's two ways of saying the same thing, "X is a pointer" = "X contains a value (of a type) that points to something".

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

Saying that multi is a pointer to a pointer is just wrong. It is a 2D array. multi can not be converted to a ** - only to *

A pointer to pointer would obviously point to a pointer. multi is not doing that. You'll find an integer at that location - not a pointer - simply because multi is not an array of pointers. multi[n] may also be converted to a * but the converted value is not taken from a place where it was stored - it is just calculated from multi.

Don't think of a 2D array like:

int a[3];
int b[3];
int c[3];
int* x[3] = {a, b, c};

cause that is simply not how 2D arrays work.

All pointer values you get from a 2D array are calculated values - not stored values.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
0

I think that there are two unrelated stuff here that you are mixing up:

  1. the name of any array of the type T[][][]...n...[] decayes into T*[][][]...n-1...[]
    for example:
    int arr [7] decayes into int* arr
    std::fstream arr[2][2] decays into std::fstream* arr[2]

by decaying, we mean that a function which can get T can also accept T' which T' is the decayed type of T

  1. you can dynamically create psuedo 2 dimentional arrays by using pointer to pointer and dynamic allcoation

    int** psuedeo2DimArray = new int*[10];
    for (auto i=0U;i<10;i++){
         psuedeo2DimArray[i] = new int[10];
    }
    

In all cases, the type of multi is int[2][2] and nothing else.

David Haim
  • 25,446
  • 3
  • 44
  • 78