0

I've read that array subscript access is the same as pointer subscript access (can't find the proper link, but http://c-faq.com/aryptr/joke.html mentions that indirectly).

So what about multidimensional access? Obviously there is no pointer at c[0] in a multidimensional array.

#include <stdio.h>

int main(){
    char c[5][2][4];
    c[1][1][2] = 'n';
    printf("\n%c", c[1][1][2]);
    char* ptr = c;
    printf("\n%c\n", ptr[1*8+4*1+2]);
}

But whatever it references (in a 3D array [d1][d2][d3]) is of size d2*d3, as that is where the imaginary pointer is offset.

Are there any docs for how this is implemented or how this can be reasoned with? In the 2D case, it makes sense, that it is just a pointer, but for the 3+ case, it is not clear if/how pointers are still being worked with.

user1122069
  • 1,767
  • 1
  • 24
  • 52
  • 1
    *All* array access is really done through the use of pointers. Remember, for any array *or pointer* `a` and index `i`, the expression `a[i]` is exactly equal to `*(a + i)`. That means an expression like `c[1][1][2]` is equal to `*(*(*(c + 1) + 1) + 2)`. Also, the best way to figure out how to use "one-dimensional" indexing is to draw the arrays out of paper, with small boxes for each element and then label each box with the corresponding index (like `c[1][1][2]` etc.) *plus* a "one-dimensional" index from zero. – Some programmer dude Jan 29 '19 at 06:46
  • [C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)](http://port70.net/~nsz/c/c11/n1570.html#6.3.2.1p3) All arrays are -- but pay attention to the 4 exceptions for when an array is not converted to a pointer to the first element on access. – David C. Rankin Jan 29 '19 at 06:49

3 Answers3

2

Seems you don't need to hear the debunking of the "arrays are pointers in disguise" lie. So I won't repeat it. But suffice it to say, that yes, all indexing happens through pointers. When you write c[0], c decays to a pointer for the purpose of indexing *(c + 0).

But a pointer to what you ask? A pointer to an array, of course. You can form those. For instance:

char d[2][4];
char (*ptr)[2][4] = &d;

Here ptr points to that array of type char[2][4]. And this is exactly the sort of pointer c decays into. That's why the multi-dimensional array school of thought in C is not too exact. We don't have those, what we have is arrays of arrays.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • The whole [array and pointers chapter](http://c-faq.com/aryptr/index.html) in the classic C FAQ is great really, since it starts by correctly addressing arrays vs pointers. – Lundin Jan 29 '19 at 07:55
  • I guess my question was about the size of the pointer as well, but this is close enough. The size of the pointed to type would be the size of everything to the right (in this case 4), so doing d[1] advances by 4 byte. I kept assuming that it had to be a char* ptr. – user1122069 Jan 29 '19 at 21:01
2

All array expression evaluations yield a pointer. If all subscripts are used, that yielded pointer is being dereferenced; any other evaluation expression will just yield a pointer value.

I emphasize "yield" to dispel with the notion that an array actually is a pointer - it is not. The mechanism is often described as "decays into a pointer", which I personally find misleading; after all, the array itself remains unchanged.

So, yes, you can reason about this as if the array access produces a temporary pointer.

GermanNerd
  • 643
  • 5
  • 12
0

The concept is explained here: With arrays, why is it the case that a[5] == 5[a]?. It is an alternative syntax allowed "by accident" to keep the language consistent, nothing else.

It has nothing to do with the container type, you can do the same obscure tricks with pointer-to-pointer as with multi-dimensional arrays. Example:

#include <stdio.h>

int main (void)
{
  char str[2][2][6] =
  {
    {"hello", "world"},
    {"foo",   "bar"}
  };

  printf("%c\n", str[0][0][0]); // print h
  printf("%c\n", 0[0[0[str]]]); // print h  (bad code, don't do this)
}

The reason why you can do things like ptr[1*8+4*1+2] is another story, namely that a multi-dimensional array is guaranteed to be allocated contiguously. This is specified in C17 6.2.5/20:

An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.

As for "imaginary pointers", how an array is accessed in machine code is up to the compiler. Sometimes it is more efficient to use direct addresses, sometimes it uses a base address + an offset. It's the kind of automatic optimization that programmers need not worry about.

Lundin
  • 195,001
  • 40
  • 254
  • 396