0

I have a 20 x 20 array and need to iterate over it by reading a 4 x 4 array. I thought I could do this with pointed assignment, but it does not do much except force close

const char SOURCE[20][20];
const char **pointer;

for(int x = 0; x < 20; x+=4)
{
    for(int y = 0; y < 20; y+=4)
    {
        pointer = (const char **)&SOURCE[x][y];
        printGrid(pointer);
    }
}

void printGrid(const char **grid)
{
    // do something usefull
}
Leon
  • 12,013
  • 5
  • 36
  • 59

4 Answers4

2

Just casting a pointer to a different type doesn't change the type of what it points to (and will usually lead to undefined behavior, unless you really know what you're doing). If you cannot change printGrid, you'll have to create an array of pointers on the fly:

for ( int x = 0; x < 20; x += 4 ) {
    for ( int y = 0; y < 20; y += 4 ) {
        char const* p4[4] =
        {
            source[x] + y,
            source[x + 1] + y,
            source[x + 2] + y,
            source[x + 3] + y
        };
        printGrid( p4 );
    }
}
James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Will it ensure that the elements of p4 are a pointer to array of 4 integers?? I think it is just array of 4 pointer to constant char. Shouldn't it be `char const (*p4[4])[4]`?? – Saksham Aug 20 '13 at 03:46
  • @Saksham Generally, the "pointer to an array" is a pointer to the first element of the array; this is what you get when you convert an array to a pointer. It's up to the user of the pointer to know whether it is a pointer to a single object, or to the first element of an array, and how many elements there are in the array. `char const (*p4[4))[4]` would be an array of pointer to an array; I couldn't initialize it without an explicit cast, because I don't have any `char const[4]` whose address I could initialize it with. And it wouldn't have the right type to pass to `printGrid`. – James Kanze Aug 20 '13 at 08:18
0

A pointer to a pointer is not the same as an array of arrays.

You can however use a pointer to an array instead:

const char (*pointer)[20];

You of course need to update the printGrid function to match the type.


As for the reason why a pointer-to-pointer and an array-of-array (also often called a matrix) see e.g. this old answer of mine that shows the memory layout of the two.

Community
  • 1
  • 1
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

Your 2D-array is of type char:

const char SOURCE[20][20];

When you are iterating through it, you can either look at the char or reference the address with a char*:

for(int x = 0; x < 20; x+=4)
{
    for(int y = 0; y < 20; y+=4)
    {
        printGrid(SOURCE[x][y]); // do this unless you need to do something with pointer
    }
}

Then you can make printGrid with either of the following signatures:

void printGrid(const char& grid)
{
    // do something usefull
}

or

void printGrid(const char* grid)
{
    // do something usefull
}
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
0

Extending James's Answer, you may change your code as below as it sees that the it passes pointer to an array of 4 char rather than just array of char.

for(int x = 0; x < 20; x+=4)
{
    for(int y = 0; y < 20; y+=4)
    {
        char const (*p4[4])[4] =
        {
            (const char(*)[4])(SOURCE[x] + y),
            (const char(*)[4])(SOURCE[x + 1] + y),
            (const char(*)[4])(SOURCE[x + 2] + y),
            (const char(*)[4])(SOURCE[x + 3] + y)
        };
    }
}
Saksham
  • 9,037
  • 7
  • 45
  • 73
  • That still won't do it. From what he says, `printGrid` expects a pointer to an array of 4 `char const*`, each of which points to 4 `char`. You're giving it a pointer to a single `char const*`, which points to an array of `20 - y` `char`. Not at all the same thing. – James Kanze Aug 19 '13 at 15:25
  • @JamesKanze Although your solution seems to be the best, any suggestions for my updated solution?? – Saksham Aug 19 '13 at 17:03
  • There seems to be too much indirection. `printGrid` needs a pointer to an array[4] of pointer, so at some point, you need a `char const *tmp[4];` (which I don't see in your code). Nothing else will do. And you pass it the address of the first element in that array (which would almost certainly be obtained by the implicit array to pointer conversion). – James Kanze Aug 19 '13 at 17:13
  • @JamesKanze now it should be fine – Saksham Aug 20 '13 at 04:07
  • The type is still wrong for his function `printGrid` (since `p4` converts implicitly to a `char const (**)[4]`, and not a `char const**`). The fact that you need the explicit conversions should be a sign that something isn't right. – James Kanze Aug 20 '13 at 08:22
  • @JamesKanze Yes I got it. I could have casted it back to `char const**` in the function call but it would have been of no use. BTW Shouldn't OP be calling `printGrid` with a pointer of type `char const (**)[4]`. Just to have a check on the boundaries in the function?? – Saksham Aug 20 '13 at 08:45
  • Not really. `char const (**)[4]` is a pointer to a pointer to an array. One level too deep. He could use `char const* (&)[4]`, but there'd still be nothing about the columns in each row. But in the end, C style arrays are broken, and we have to live with it. (In C++ 11, `std::array` would be a good choice.) – James Kanze Aug 20 '13 at 09:23