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

时间:2019-03-19 14:45:49

标签: c arrays pointers struct

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}}

3 个答案:

答案 0 :(得分:2)

请注意,从技术上讲,这不是二维数组,而是指针到指针的数组。但是,由于复合文字不能具有可变长度的数组类型,而且似乎也不希望使用硬编码维,所以这可能是唯一的方法。

您需要将数组拆分为未知大小的一维数组,并为其使用单独的复合文字:

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

答案 1 :(得分:1)

首先,size_t **point仅在您打算指向size_t*的数组时才有意义。在这里似乎情况并非如此,因此您需要将类型更改为2D数组或数组指针。

下一个问题是C在这里相当麻烦-坦率地说,您不能有“静态动态”数组,它必须是。您可以拥有这个:

#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

或另外一种可能是指针数组形式的灵活数组成员,如下所示:

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);

这些都不是特别好的替代方法,语法混乱且容易出错。这里根本缺少语言。

答案 2 :(得分:0)

为了静态地初始化指针,需要声明您指向的实体。仅在极少数情况下,例如可能在嵌入式系统中您在编译时就知道某物的地址,才知道要静态初始化的指针的实际值。

我发现您的操作存在一些问题: 1)尝试使用n声明数组大小时,编译器无法解析n的值。与C#不同,数组需要在声明中提供大小。 2)结构的“ point”成员是一个指向指针的指针,但是您尝试使用数组数组对其进行初始化。如果要指向数组数组,则只需要[0] [0]元素的地址,因此* point不需要* point。从那里可以使用数组符号访问元素。

您需要执行以下操作:

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
}

然后您可以通过以下方式访问阵列:

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

如果您确实需要指向指针的指针,则初始化值必须是地址引用(&name)或被转换为指针的值,但是我不建议这样做。

如果您确实需要为数组提供可变大小,则需要动态分配内存,然后使用该结构返回的地址初始化结构体中的指针。