views:

56

answers:

4

Okay, I have a multi-dimensional array which is statically-allocated. I'd very much like to get a pointer to a portion of it and use that pointer to access the rest of it. Basically, I'd like to be able to do something like this:

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

#define DIM1 4
#define DIM2 4
#define DIM3 8
#define DIM4 64

static char theArray[DIM1][DIM2][DIM3][DIM4] = {0};

int main()
{
    strcpy(theArray[0][0][0], "hello world");

    char** ptr = theArray[0][0];

    printf("%s\n", ptr[0]);

    return 0;
}s

This code results in this error using gcc:

t.c: In function ‘main’:
t.c:17: warning: initialization from incompatible pointer type

char** is apparently not the correct type to use here. I assume it's because statically-allocated arrays are created as a single block in memory while dynamically allocated ones are separated in memory, with each dimension having a pointer to the next one.

However, as you likely noticed, the number of dimensions here is painfully large, and I'm obviously going to need to use actual variables to index the array rather than the nice, slim character 0, so it's going to get painfully long to index the array in actual code. I'd very much like to have a pointer into the array to use so that accessing the array is much less painful. But I can't figure out the correct syntax - if there even is any. So, any help would be appreciated. Thanks.

+3  A: 

theArray[0][0] gets rid of the first two dimensions, so you have something of type char [DIM3][DIM4]. The first dimension will drop out when the array decays to a pointer, so the declaration you want is:

char (*ptr)[DIM4] = theArray[0][0];

For what it's worth, gcc also displays a warning for your array declaration: "warning: missing braces around initializer". Static variables and global variables will automatically be initialized to 0, so you can fix the warning by getting rid of the initializer:

static char theArray[DIM1][DIM2][DIM3][DIM4];
John Kugelman
It's not so much "variables at global scope" as "variables with static storage duration" (of which "variables at global scope" are a subset).
caf
Good point, updated answer, though trying to avoid standard-ese.
John Kugelman
A: 

Does not matter that it is static, your types don't match

Why a double pointer can't be used as a 2D array?

This is a good example, although the compiler may not complain, it is wrong to declare: "int **mat" and then use "mat" as a 2D array. These are two very different data-types and using them you access different locations in memory. On a good machine (e.g. VAX/VMS) this mistake aborts the program with a "memory access violation" error.

This mistake is common because it is easy to forget that the decay convention mustn't be applied recursively (more than once) to the same array, so a 2D array is NOT equivalent to a double pointer.

A "pointer to pointer of T" can't serve as a "2D array of T". The 2D array is "equivalent" to a "pointer to row of T", and this is very different from "pointer to pointer of T".

When a double pointer that points to the first element of an array, is used with subscript notation "ptr[0][0]", it is fully dereferenced two times (see rule #5). After two full dereferencings the resulting object will have an address equal to whatever value was found INSIDE the first element of the array. Since the first element contains our data, we would have wild memory accesses. ...

etc.... http://www.ibiblio.org/pub/languages/fortran/append-c.html

f0ster
+3  A: 
John Bode
+1  A: 

If you are using Visual Studio, a nice way to find out the type of the expression is to use typeid.

cout << typeid(&theArray[0][0]).name();

which prints

char (*)[8][64]

But note that output of typeid().name() is an implementation specific behavior and as such can not be relied upon. But VS happens to be nice in this regards by printing a more meaningful name

Chubsdad