0

So, I've figured out how to dereference a multidimensional array like this:

#include <tchar.h>
#include <iostream>

wchar_t g_pppwcSymbol[2][3][4];

int main(int argc, TCHAR **argv) 
 {
     (* (*( (*(g_pppwcSymbol+1) )+2 )+3 ) ) = L'K';
     std::wcout<<g_pppwcSymbol[1][2][3];
     std::wcin.get();
     return 0;
 }

Output: K

However, I've also heard that the compiler transforms this into a 1-dimensional array, is that correct? This would mean that all the wchar_t elements follow up each other in the memory. So there must be a way to do something like this:

***(g_pppwcSymbol + x) = value;

However I'm not sure how this works exactly. Could someone elaborate?


EDIT:

this seems to work so far:

int main(int argc, TCHAR **argv) 
 {
     /*(* (*( (*(g_pppwcSymbol+1) )+2 ) + 3)) = L'K';*/
     /*std::wcout<<g_pppwcSymbol[1][2][3];*/
     ***(g_pppwcSymbol + 1) = L'K';
     std::wcout<<g_pppwcSymbol[1][0][0];
     std::wcin.get();
     return 0;
 }

output: K


NEXT EDIT:

Working model:

static const int X = 2;
static const int Y = 3;
static const int Z = 4;
wchar_t g_pppwcSymbol[X][Y][Z];

int main(int argc, TCHAR **argv) 
 {
     int iAccess = ((Y*Z) * 1) + ((Z) * 2) + 3;
     *( (**g_pppwcSymbol) +  iAccess) = L'K';
     std::wcout<<g_pppwcSymbol[1][2][3];
     std::wcin.get();
     return 0;
 }

Output: K

xcrypt
  • 3,276
  • 5
  • 39
  • 63
  • 2
    Have you tried it? While the compiler may be virtually forced to allow this to work, it's undefined behaviour nonetheless. – Kerrek SB Sep 28 '11 at 23:11
  • @Kerrek SB Why is it undefined behaviour? Because you can't know how the compiler will implement this? – xcrypt Sep 28 '11 at 23:15
  • 1
    No, just because the standard says so. It says that accessing an array with any index that's not in the array bounds, or dereferencing a pointer that does not point inside an array of the correct size, is undefined behaviour. The right-most asterisk on your last line causes the UB. – Kerrek SB Sep 28 '11 at 23:16
  • 1
    @KerrekSB: are you sure it's UB? I remember arguing another time about multidimensional arrays, and it turned out that something like that was legal (but I'm not entirely sure that it was *this* thing). – Matteo Italia Sep 28 '11 at 23:16
  • @MatteoItalia: Do dig that up if you have it, I was thinking about that, too. But I think it's UB, just so that it's impossible to not get the desired result, because of the requirement how arrays are to be laid out. – Kerrek SB Sep 28 '11 at 23:18
  • @KerrekSB: N3242 [dcl.array] ¶8 seems to confirm this, but I have to double-check. – Matteo Italia Sep 28 '11 at 23:20
  • @xcrypt: still, I suppose you meant `*(**g_pppwcSymbol+x) = value` if you want to index your 3-d array as a 1-d array. – Matteo Italia Sep 28 '11 at 23:22
  • @KerrekSB: [here](http://stackoverflow.com/questions/7164689/g-warning-on-declaring-multidimensional-double-array/7164753#7164753) the argument I remember, [here](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c/4810676#4810676) the related c++-faq entry. – Matteo Italia Sep 28 '11 at 23:24
  • @Matteo Italia Are you sure it matters? It doesn't seem to – xcrypt Sep 28 '11 at 23:32
  • 1
    @xcrypt: in your code the result should be the element `[x][0][0]`, so you can't iterate over the whole container with it (you get only to the first element of each "row"); instead, the code I posted gets the pointer to the first element, and then uses `x` as a "flattified array index". Actually, you can more simply do `array[0][0][x]` or `(**array)[x]` and use x from 0 to one less the product of the dimensions. – Matteo Italia Sep 28 '11 at 23:35
  • Digging deeper through those links, I found the interesting statement that we shouldn't think of pointers as addresses, but rather just as pointers. They behave like pointers promise to behave, and the way they're implemented (usually as addresses, but apparently on flash memory you need something else) is not our business. So we have to abide by the rules of pointer arithmetic, which say that you mustn't increment a pointer by more than the array size. – Kerrek SB Sep 28 '11 at 23:36
  • 2
    If the elements inside your array are arrays too, you never actually navigate outside of the array size. You simply get more precise within your array. You start with large chunks to select from which array you select, then skip smaller chunks to select within the inner array, then even smaller chunks to get the element. – Kevin Coulombe Sep 28 '11 at 23:43
  • @KerrekSB: I am still unsure about whether accessing an element beyond the end of *one array* is undefined behavior, or only beyond the end of the *full object*. There are many questions for which the answer seems to indicate that using a pointer to the first element of the innermost array and falling off the end of that first innermost array will lead the pointer to refer to the first element of the second innermost array. Pointer arithmetic ensures that in `int a[2][3];`, `&a[1][0] == (int*)&(a[1]) == (int*)((char*)&a + sizeof(int[3]))`... Note that you are always within the same object. – David Rodríguez - dribeas Sep 29 '11 at 00:10

1 Answers1

1

The compiler actually transforms the [] operator into just those mathematical calculations, so you are going about this the hard way... But it's an interesting exercise so I'll play along.


g_pppwcSymbol[2][3][4] is actually a 2 elements large array of 3 elements large array of 4 elements large. Thus,

g_pppwcSymbol + ((3 * 4) /* size of first level array element */ * 1) + (4 /* size of second level array element */ * 2) + 1 /* size of third level array element */ * 3;

should give you the position of the last item of the last array of the last array. As long as each element is 1 byte large.

The array simply is a memory area the size of "element_count * element_size and the [] operator takes the array location as a pointer and adds element_size * index. It may contain other arrays since it can compute their sizes the same way as other memory structures.

BTW, I'm sure you'll find plenty of documentation about this in details all over the internet.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Kevin Coulombe
  • 1,517
  • 1
  • 17
  • 35