【问题标题】:Array of pointers to multidimensional arrays指向多维数组的指针数组
【发布时间】:2009-04-28 18:56:48
【问题描述】:

我有一些二维数组,例如:

int shape1[3][5] =  {1,0,0,
             1,0,0,
             1,0,0,
             1,0,0,
             1,0,0};
int shape2[3][5] =  {0,0,0,
             0,0,0,
             0,1,1,
             1,1,0,
             0,1,0};

等等。

如何创建指向这些指针的数组?

我尝试了以下方法,但它们不起作用(警告:从不兼容的指针类型初始化):

int *shapes[]=  {&shape1,&shape2};

int *shapes[]=  {shape1,shape2};

int **shapes[]= {&shape1,shape2};

有什么帮助吗?

【问题讨论】:

    标签: c arrays pointers


    【解决方案1】:

    我相信我刚刚验证了我写的内容是正确的。以下按预期工作:

    #include <stdio.h>
    
    int main(int argc, char **argv) {
    
    int shape1[5][3] =  {1,0,0,
                     1,0,0,
                     1,0,0,
                     1,0,0,
                     1,0,0};
    
    int shape2[5][3] =  {0,0,0,
                     0,0,0,
                     0,1,1,
                     1,1,0,
                     0,1,0};
    
    typedef int (*shapes_p)[3];
    shapes_p shapes[2] = { shape1, shape2 };
    
    shapes[0][1][0] = 5;
    shapes[1][1][0] = 5;
    
    printf("shape1[1][0] == %d\n", shape1[1][0]);
    printf("shape2[1][0] == %d\n", shape2[1][0]);
    
    }
    

    要记住的是shape1shape2的类型实际上是:

    int *shape1[5];

    您在内存中拥有的是 3 个相邻的数组,每个数组有 5 个整数。但实际类型是指向 5 个整数数组的指针。当你写:

    shape1[1][2] = 1;

    您是在告诉编译器索引 int[5] 的第二个数组,然后访问该数组的第三个元素。编译器实际上所做的是对指向的基础类型的指针运算,在本例中为 int[5]。你可以用下面的代码做同样的事情:

    int *p = shapes1[0];
    p+7 = 1;  // same as shape1[1][2] = 1;
    

    所以如果你想要一个指向 int *[5] 的指针数组,那么你会这样做:

    typedef int (*shapes_p)[5];
    shapes_p shapes[2];
    

    【讨论】:

    • -1 抱歉 -- shape1 的类型实际上是“int shape1[3][5]”,只是 在表达式中使用名称 shape1 会产生一个“int *[5]”类型的值(即指向数组第一个元素的指针)。
    • 也许我遗漏了一些东西,但我检查了我的解决方案,它按预期工作。我在文章开头添加了一个完整的可编译示例。
    • 我很抱歉罗伯特,你完全正确。您将使用“T *ptr”来访问 T 的一维数组,因此您应该使用“T (*ptr)[3]”来访问行宽为 3 的二维 T 数组。+1。跨度>
    • 我希望澄清这个问题的一个基本方面。不确定这是否应该是一个新问题,所以我将从这里开始。此方法严格为指针分配内存(当然,最终是它们的数组),绝不会为指针和 int 的底层数组分配内存,对吗?那么,shape1 消耗的空间量并没有被复制?或者,换一种说法,int (*shapes_p)[5] 定义的整体类型和分配给它的相应内存仍然只是一个指针?
    【解决方案2】:

    更新固定类型。感谢j_radom_hacker 引起我的注意!

    [编辑:实际上这里的类型不正确——请参阅 Robert S. Barnes' answer 以了解要使用的正确类型。]

    先搞清楚shape1shape2的类型:

    typedef int (*shape_array_t)[5];
    

    现在使用这个:

    shape_array_t sat[] = { shape1, shape2 };
    

    【讨论】:

    • 嘿,我打错了——对不起:P
    • @j_random_hacker:我想我在你发表评论之前修复了它;-)
    • 实际上,我仔细阅读了 Robert Barnes 的回答,他是对的——我们不应该在 sat 的类型中包含外部下标 ("[3]")。就目前而言,要使用您(或我的原始)代码访问单个 int,您需要编写例如"sat[1][0][2][4]" -- second 下标,"[0]",需要选择第一个 3x5 数组!
    • @dirkgently:我刻意编辑了你的答案,所以我可以 -1...错误的。 (我自己的答案也是如此,您可能应该投反对票。)
    • 我刚刚确定了答案。我不会因为投反对票而烦恼自己,但我会给罗伯特 +1。
    【解决方案3】:

    首先,第一个数组绑定是指最外层的数组维度,所以你应该将shape1声明为:

    int shape1[5][3] =  {1,0,0,
                         1,0,0,
                         1,0,0,
                         1,0,0,
                         1,0,0};
    

    shape2 也是如此。

    [编辑:我已将下面shapes 的类型更改为与Robert Barnes' answer 相对应——我们不希望最外层的下标包含在此类型中!]

    你需要的看起来有点奇怪的类型名是:

    int (*shapes[])[3] = { shape1, shape2 };
    

    这允许使用 shape2 的第 4 行第 1 列的元素来寻址

    shapes[1][3][0]
    

    子表达式及其 C 类型的细分:

    shapes            // has type "int (*x[2])[3]" (decays to "(**x)[3]")
    shapes[1]         // has type "int (*x)[3]"
    shapes[1][3]      // has type "int x[3]" (decays to "int *x")
    shapes[1][3][0]   // has type "int x"
    

    (请注意,上面的类型中包含了一个虚拟的x 以使它们更清晰——实际上这个标识符不是类型的一部分。)

    解码 C/C++ 类型的经验法则是“从变量名开始,尽可能向右读取,在遇到右括号时向左读取。”所以shapes 的解码类型名是:

    指向 3 个整数数组的指针数组。

    一般来说,将typedefs 用于这些复杂类型会更好,例如dirkgently suggests

    【讨论】:

      猜你喜欢
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多