简体   繁体   中英

How static initialize a 2D array to a pointer to pointers?

I have a structure, say foo that looks like this,

struct foo {
    size_t n;
    size_t **point;
};

There are other members in the structure they are not important to the question. Now, I want to static initialize the structure.

int main(void)
{
    struct foo *bar = &(struct foo){
                       .n=4,
    /* ERROR HERE */   .point=(size_t[][n]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
    };
    return 0;
}

There are two problem in the line indicated. First, understandably the compiler doesn't recognise n and is there any way I can do something similar without creating a variable before? Secondly, and most importantly, I realized that I have no idea how to create a 2D array and assign it to a pointer to pointers statically. Please help. I tried the following variations but nothing worked.

/* Variation 1 */   .point=(size_t[][4]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
/* Variation 2 */   .point=(size_t**)(size_t[][4]){ {1, 2, 3, 4}, {5, 6, 7, 8}}
/* Variation 3 */   .point=&(size_t[][4]){ {1, 2, 3, 4}, {5, 6, 7, 8}}

Note that this isn't technically 2D array, but a pointer-to-pointer array. But since compound literals cannot have variable length array type, and it doesn't seem that you want to use hardcoded dimensions, this may be the only way to go.

You'll need to split your arrays to 1D arrays of unknown size and use separate compound literals for them:

struct foo * bar = &(struct foo){
    .n = 4,
    .point = (size_t*[]){
        (size_t[]){1, 2, 3, 4}, 
        (size_t[]){5, 6, 7, 8}
    }
};

First of all size_t **point only makes sense if you intend to point at an array of size_t* . That doesn't seem to be the case here, so you need to change the type to a 2D array, or an array pointer.

Next problem is that C is rather cumbersome here - bluntly put, you can't have a "static dynamic" array, it must be either. You can either have this:

#define N 4

struct foo {
  size_t n;
  size_t (*point)[N]; // pointer to first array of an array of size_t[4]
};

struct foo bar = 
{
  .n=N,
  .point= (size_t[][N]){ {1, 2, 3, 4}, {5, 6, 7, 8} }
};

...
bar.point[x][y] = ...; // access element of the 2D array

or alternatively perhaps a flexible array member in the form of an array of pointers, like this:

struct foo {
  size_t n;
  size_t* point[];
};

const size_t n = 4;
struct foo* bar = malloc ( sizeof(*bar) + sizeof (size_t*[n]) );
bar->n = n;
bar->point[0] = (size_t []) { 1, 2, ... /* any number of elements*/ };
bar->point[1] = ...
...
bar->point[0][0] = 0; // access element in the lookup-table
...
free(bar);

None of these are particularly good alternatives, the syntax is messy and error prone. The language is simply severely lacking here.

In order to initialize a pointer statically, the entities you are pointing to need to have been declared. Only in rare cases, like maybe an embedded system where you know the address of something at compile time, would you know the actual value of the pointer to be initialized statically.

I see a couple problems with what you're doing: 1) The compiler can't resolve what the value of n is at the time you are trying to use it to declare the size of your array. Arrays need to have a size supplied in their declaration, unlike C#. 2) The "point" member of the struct is a pointer to pointers, but you're trying to initialize it with an array of arrays. If you want to point to an array of arrays, you only need the address of the [0][0] element, so *point not **point. From there you can use array notation to access the elements.

You need to do something like this:

struct foo
{
    size_t n;
    size_t *point;
};


size_t values[2][4] = {{1,2,3,4}, {5,6,7,8}};

struct foo bar = 
{
    4,
    &values
}

Then you can access the array by:

size_t kk;
kk = bar.point[ii][jj];

If you truly need pointers to pointers, then the initialization values will have to either be address references (&name) or values that are being cast as pointers, but I don't suggest doing that.

If you truly need a variable size for your array, then you'll need to allocate memory dynamically and then initialize the pointer in the struct with the address returned from that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM