0

Given the following code, I'm trying to understand if the pointer manipulation is legit:

struct Foo{
 int *temp1;
}

temp1 => 2d array

struct Foo1{
 int temp1[2][2];
}

temp1 => 3d array

struct Foo2{
 int temp1[3][2][3];
}

I assign value to Foo1 and Foo2 using static data. For e.g.:

Foo1 f1 =
{
 { 2, 4 },
 { 1, 3 }
};

Foo2 f2 = 
{
   {
       {
           {101, 102, 103},
           {104, 105, 106},
       },
       {
           {107, 108, 109},
           {110, 111, 112},
       },
       {
           {113, 114, 115},
           {116, 117, 118},
       },
   }
};

Can I reference Foo data from Foo1 like this:

Foo f;
f.temp1 = (int*)f1.temp1;
for(int i = 0; i < 2; ++i)
{
 for(int j = 0; j < 2; ++j)
 {
  cout << "i " << i << " j " << j << " value: " << f.temp1[(i * 2) + j] << endl;
 }
}

Can I reference Foo data from Foo2 like this:

Foo f;
f.temp1 = (int*)f2.temp1;
for(int i = 0; i < 3; ++i)
{
 for(int j = 0; j < 2; ++j)
 {
   for(int k = 0; k < 3; ++k)
   {
    cout << "i " << i << " j " << j << " k " << k << " value: " << f.temp1[(i * 3 * 2) + (j * 2) + k] << endl;
   }
 }
}

Essentially, I am assuming the array is going to arranged in contiguous memory and can I dereference it like this ?

Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
brainydexter
  • 19,826
  • 28
  • 77
  • 115
  • Do you have a good reason *not* to use STD containers? – Biffen May 21 '14 at 06:14
  • @Biffen: Yes. If I use vectors (and nope, cant do c++1x either), I will have to copy the data into those containers which is a big no-no for this requirement. I have a LOT of data and copying it into these containers will take a lot of time, which is not acceptable in my environment. – brainydexter May 21 '14 at 18:14
  • Sounds like a good reason. :) – Biffen May 21 '14 at 18:17

2 Answers2

1

The answer to this question suggests that the answer is yes. Multidimensional arrays are indeed laid out contiguously in memory, assuming they are declared with the [size1][size2][size3] notation.

Empirically, the answer is also yes. Consider the following code, which I wrote by cobbling together the fragments you wrote in your question.

#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;
struct Foo {
    int *temp1;
};

struct Foo1{
    int temp1[2][2];
};

struct Foo2{
    int temp1[3][2][3];
};


Foo1 f1 =
{
    {
        { 2, 4 },
        { 1, 3 }
    }
};
Foo2 f2 = 
{
    {
        {
            {101, 102, 103},
            {104, 105, 106},
        },
        {
            {107, 108, 109},
            {110, 111, 112},
        },
        {
            {113, 114, 115},
            {116, 117, 118},
        },
    }
};


int main(){


    int* temp1 = (int*) f1.temp1;
    for(int i = 0; i < 2; ++i)
        for(int j = 0; j < 2; ++j)
            cout << "i " << i << " j " << j << " value: " 
                << temp1[(i * 2) + j] << endl;

    temp1 = (int*) f2.temp1;
    cout << endl;
    for(int i = 0; i < 3; ++i)
        for(int j = 0; j < 2; ++j)
            for(int k = 0; k < 3; ++k)
                cout << "i " << i << " j " << j << " k " << k << " value: " 
                    << temp1[(i * 3 * 2) + (j * 3) + k] << endl;
}

Output:

i 0 j 0 value: 2
i 0 j 1 value: 4
i 1 j 0 value: 1
i 1 j 1 value: 3

i 0 j 0 k 0 value: 101
i 0 j 0 k 1 value: 102
i 0 j 0 k 2 value: 103
i 0 j 1 k 0 value: 104
i 0 j 1 k 1 value: 105
i 0 j 1 k 2 value: 106
i 1 j 0 k 0 value: 107
i 1 j 0 k 1 value: 108
i 1 j 0 k 2 value: 109
i 1 j 1 k 0 value: 110
i 1 j 1 k 1 value: 111
i 1 j 1 k 2 value: 112
i 2 j 0 k 0 value: 113
i 2 j 0 k 1 value: 114
i 2 j 0 k 2 value: 115
i 2 j 1 k 0 value: 116
i 2 j 1 k 1 value: 117
i 2 j 1 k 2 value: 118
Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • I have a question from the link you referenced. So, we can't really use `int**` for 2d arrays, but use a single pointer as I mentioned above ? – brainydexter May 21 '14 at 18:17
1

The standard says clearly and explicitly that the answer is yes. See n3797 s8.3.4. Some of the language is hard to read, but the final note says:

[Note: It follows from all this that arrays in C++ are stored row-wise (last subscript varies fastest) and that the first subscript in the declaration helps determine the amount of storage consumed by an array but plays no other part in subscript calculations. —end note ]

So you can reference the storage in any array by a calculation that uses simple pointer arithmetic, and iterate over all the storage in any array simply by incrementing a pointer.

Please note that arrays are not required to be packed. They usually are, but there could be padding inserted between elements (but not extra padding between rows or columns).

david.pfx
  • 10,520
  • 3
  • 30
  • 63