简体   繁体   English

在函数内分配2D连续数组

[英]Allocating a 2D contiguous array within a function

I am trying to allocate a 2d contiguous array using C99 variable length arrays. 我正在尝试使用C99可变长度数组分配2d连续数组。 Something like this: 像这样:

size_t rows = 5, cols = 5;
double (*array)[cols] = malloc(rows * sizeof *array);

The trouble is, I want to do the allocation in a function. 麻烦的是,我想在一个函数中进行分配。 I'm guessing that in order to do so, I need to declare the array first and then pass its address to the function. 我猜想为了这样做,我需要先声明数组,然后将其地址传递给函数。 I've been trying things like this: 我一直在尝试这样的事情:

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

void allocate(double *((*grid)[]), size_t cols)
{
    size_t rows = 5; // in practice this the result of a computation
    double (*array)[cols] = malloc(rows * sizeof *array);
    *grid = array;
}


int main ()
{
    size_t cols = 5;
    double (*grid)[cols];    // note: edited to fix typo (was [])
    allocate(&grid, cols);

    return 0;
}

My compiler (GCC 4.7.1) is giving me the following warnings/errors: 我的编译器(GCC 4.7.1)给我以下警告/错误:

$ gcc -Wall -pedantic -std=c99 2d.c -o 2d
2d.c: In function ‘allocate’:
2d.c:8:5: error: invalid use of array with unspecified bounds
2d.c: In function ‘main’:
2d.c:16:5: warning: passing argument 1 of ‘allocate’ from incompatible pointer type [enabled by default]
2d.c:4:6: note: expected ‘double * (*)[]’ but argument is of type ‘double (**)[]’

I have tried many variations of this kind of thing but I am clearly missing something. 我已经尝试过这种事情的许多变体,但是我显然缺少一些东西。 I would like to have a contiguous 2d array accessible like grid[j][i] from main but perform the allocation in a separate function. 我想有一个可以从maingrid[j][i]那样访问的连续2d数组,但是要在单独的函数中执行分配。 How can I do this? 我怎样才能做到这一点?

Change 更改

void allocate(double *((*grid)[]), size_t cols)   
                      //    ^grid is pointer to array of `double *` type 

to

void allocate(double (**grid)[], size_t cols)  
                      //   ^grid is a pointer to pointer to array of `double` type  

You definitely can return a pointer-to-multidimensional-VLA. 您绝对可以返回指向多维VLA的指针。 I'm not sure if one can declare a function with such a return type, but hey, why not just return void * instead? 我不确定是否可以用这种返回类型声明一个函数,但是,为什么不返回void *呢?

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

void *allocate(size_t n, size_t k)
{
    int (*p)[n] = malloc(k * sizeof *p);
    for (size_t i = 0; i < k; i++) {
        for (size_t j = 0; j < n; j++) {
            p[i][j] = i * j;
        }
    }

    return p;
}


int main(void)
{
    size_t n = 3, k = 5;
    int (*p)[n] = allocate(n, k);

    for (size_t i = 0; i < k; i++) {
        for (size_t j = 0; j < n; j++) {
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }

    free(p);
    return 0;
}
void allocate( size_t cols, double (**arr)[cols] )
{
  size_t rows = ...;
  *arr = malloc( sizeof **arr * rows );
}

Edit 编辑

Complete example: 完整的例子:

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

size_t get_rows( void )
{
  return 5;
}

void allocate( size_t cols, double (**arr)[cols] )
{
  size_t rows = get_rows();
  *arr = malloc( sizeof **arr * rows );
  if ( *arr )
  {
    for (size_t r = 0; r < rows; r++ )
      for (size_t c = 0; c < cols; c++ )
        (*arr)[r][c] = r * cols + c;
  }
}

int main( void )
{
  size_t cols = 5;
  double (*arr)[cols] = NULL;
  allocate( cols, &arr );
  for ( size_t r = 0; r < get_rows(); r++ )
    for ( size_t c = 0; c < cols; c++ )
      printf( "arr[%zu][%zu] = %.2f\n", r, c, arr[r][c] );

  free( arr );
  return 0;
}

If you want to allocate a contiguous two-dimensional array (as C does with static 2D arrays), your malloc will look like 如果要分配连续的二维数组(如C对静态2D数组所做的那样),则malloc看起来像

element_type *array = malloc(rows * cols * sizeof *array);

To access the array you'll have to do pointer arithmetic yourself: 要访问数组,您必须自己进行指针运算:

*(array + i*cols + j);

The code you describe is more akin to jagged arrays . 您描述的代码更类似于锯齿数组

The following works for me: 以下对我有用:

static void
xalloc(int rows, int cols, double (**array)[cols])
{
  *array = malloc(rows * sizeof(**array)) ;

  double* p = (void*)*array ;
  for (int i = 0 ; i < (rows * cols) ; ++i)
    p[i] = i ;
} ;

int
main()
{
  int rows = 10 ;
  int cols =  7 ;

  double (*array)[cols] ;
  xalloc(rows, cols, &array) ;

  for (int r = 0 ; r < rows ; ++r)
    {
      printf("%3d:", r) ;
      for (int c = 0 ; c < cols ; ++c)
        printf("%3d:%4.0f", c, array[r][c]) ;
      printf("\n") ;
    } ;
} ;

Which I think is consistent with the desire to use a Variably Modified type for the array. 我认为这与对数组使用Varially Modified类型的愿望是一致的。

Mind you, I also think it's horrible... but hey, it's not every day one gets to write something quite so abstruse as double (*array)[cols] and get away with it. 提醒您,我也认为这太可怕了……但是,嘿,并不是每天都有人写出像double (*array)[cols]这样抽象的东西,然后逃避它。

Try changing your code like below. 尝试如下更改代码。

void allocate (double ((**grid) []), size_t cols) {
    size_t rows = 5;
    double (*arr)[] = (double (*)[]) malloc (rows * sizeof (size_t));
    *grid = arr;
}

int main () {
    size_t cols = 5;
    double (*grid)[] = 0;
    allocate (&grid, cols);
    printf ("%x", (void *)grid); // to show that the memory is being allocated
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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