【问题标题】:Can I declare a pointer to a 2d array before I know the dimensions?我可以在知道维度之前声明一个指向二维数组的指针吗?
【发布时间】:2016-01-12 21:20:55
【问题描述】:

我知道声明指向二维数组的指针的一种方法是这样的:

int(*p)[100];

然后将它分配给某物后,我可以使用这样的元素:

p[1][6] = 18;

但是假设我还不知道数组的维度,我打算在发现时对它们进行 malloc。

一个解决方案是我声明一个指向一个 int 的指针,然后使用指针算法来导航数组。我通常这样做,但这次为了方便起见,我想使用方括号表示法。

那么当我还不知道尺寸并且打算使用方括号表示法时,如何声明这个指针呢?

【问题讨论】:

  • 有数组数组,也有指针数组。您可以使用后者来导航类似二维数组的结构,而无需事先知道尺寸。你不能在 C89 中使用前者,因为你甚至不能在不知道至少内部维度的情况下提及它的类型。在 C99 及更高版本中,您可以使用 VLA,但它们有其局限性。
  • @nm: int (*p)[CONSTANT_LENGTH] 是指向数组的普通指针,而不是 VLA 或类似的指针,那么为什么不符合 C89(撇开使用 C99 或 C11 通常是一个好主意除外) ?请注意,它不同于指针数组:int *p[CONSTANT_DIM]
  • @Olaf 它当然是合规的,但需要事先知道 CONSTANT_LENGTH,这不是 OP 要求的。
  • @n.m.:对不起,我只读了dimension,不是复数。但是,定义一个指向 VLA 的指针应该可以工作。

标签: c arrays pointers


【解决方案1】:

那么当我还不知道尺寸并且打算使用方括号表示法时,我该如何声明这个指针呢?

您可以使用指向指针的指针。

int** p = NULL;

以后……

p = malloc(N*sizeof(int*));
for (int i = 0; i < N; ++i )
{
   p[i] = malloc(M*sizeof(int));
}

并确保在多个步骤中解除分配。

for (int i = 0; i < N; ++i )
{
   free(p[i]);
}
free(p);

另一种方式。

// Allocate memory for the pointers.
p = malloc(N*sizeof(int*));

// Allocate memory for the ints.
p[0] = malloc(M*N*sizeof(int));

// Assign the values to the elements of p.
for (int i = 1; i < N; ++i )
{
   p[i] = p[i-1] + M;
}

只需两步即可解除分配。

free(p[0]);
free(p);

【讨论】:

  • 为什么不malloc(sizeof(int) * M * N)
  • @cad 你也可以这样做。
  • @cad,使用p = malloc(sizeof(int) * M * N)你不能使用数组下标p[1][6] = 18;
  • @AlterMann,你也可以这样做。请参阅我的回答中的“另一种方式”。
  • @RSahu,是的,“另一种方式”是避免内存碎片的好方法。
【解决方案2】:

只需使用指向可变长度数组的指针。

你的尺寸,y 行 x 元素:

size_t x = 123;
size_t y = 30;

一键分配,sizeof(*p) 等同于sizeof(int) * 123

int (*p)[x] = malloc( sizeof(*p) * y );

并迭代二维数组:

for( size_t i = 0 ; i < y ; i++ )
    for( size_t j = 0 ; j < x ; j++ )  
        p[i][j] = 0;

【讨论】:

  • 请注意是否可以在指针初始化之前使用sizeof(*vla) 进行了讨论。虽然我同意这是允许的,但标准的文本可能会产生误导。这可以通过显式使用sizeof(int) * x * y) 来避免。
  • @Olaf 所以你是说应该初始化指针以避免那个 ub,但是取消引用不是问题吗?
  • stackoverflow.com/questions/32985424/… 我不支持接受的答案,但支持 Keith Thompson 的答案。也请阅读 cmets。
  • @Olaf 我做到了。编译器会按照 Keith 最后得出的结论去做,但我认为标准仍然模棱两可。我们是否应该认真地开始编写 sizeof( int[y][x] ) 来确定一下?
【解决方案3】:
int(*p)[100];

这不是你想要的。这是指向int 数组的指针。

你想要的是指向int的指针。

int **p;
p=malloc(sizeof(int *)*r);       // allocate memory for r number of int *
for(int i=0;i<r;i++)
    p[i]=malloc(sizeof(int)*c);  //  allocate memory to each pointer  

free 以类似的方式。

【讨论】:

  • 这不是一个二维数组,而是一个一维指针数组,显然不是 OP 所要求的。
【解决方案4】:

要索引数组而不是指针数组,可以使用以下技巧:

#include <stdlib.h>
#include <stdio.h>

void f( const size_t m, const size_t n, const char s[m][n] )
{
   printf( "%s, %s!\n", s[0], s[1] );
   return;
}

int main(void) {
    static const char hello[][6] = { "hello", "world" };
    f( sizeof(hello)/sizeof(hello[0]), sizeof(hello[0]), hello );

    return EXIT_SUCCESS;
}

您的问题被标记为 C 而不是 C++,但 C++ 确实引用了数组:int (&amp;foo)[m][n] = bar;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    相关资源
    最近更新 更多