C中的指针数组等价使用不同维度的数组

时间:2015-08-31 15:04:37

标签: c arrays pointers

我已经查看了其他问题,他们似乎无法回答这个问题。

我有一个例程,我想处理一个可能是一维或二维的整数数组

这样:

int myarray[10];

int myarray[10][10];
void myroutine(int *input_array, int num_dimens)
{
   int digits;
   int limbs;
   int i, j;

   digits = get_num_digits();
   if (num_dimens == 1)
   {
      for(i=0; i< digits; i++)
         myprocess(*(input_array+i));
   } else { /* 2 dimensions */
      limbs = get_num_limbs();
      for(j=0;j<limbs;j++)
         for(i=0; i< digits; i++)
           myprocess(*(input_array+j*digits+i));
   }
}

如何调用 myroutine

myroutine(myarray, 1);
myroutine(myarray2, 2);

这似乎不起作用。 新编辑:试图进一步充实这个例子。

7 个答案:

答案 0 :(得分:2)

假设你真的想要编写一个伪多态函数来处理不同的数组类型(意思是,不同数量的维度和长度),你需要将一个显式指针传递给第一个要素:

myroutine( &myarray[0], 1 );
myroutine( &myarray2[0][0], 2 );

这样你的第一个输入始终是int *

在您的例程中,您将input_array对象视为一维数组:

// input_array is a 1D array
input_array[i] = something;

// input_array is a 2D array
input_array[ i * d0 + j ] = something;

// input_array is a 3D array
input_array[i * d0 * d1 + j * d1 + k ] = something;

您需要将维度长度作为附加参数传递,例如:

myroutine( &myarray[0], 1, 10 );
myroutine( &myarray2[0][0], 2, 10, 10 );
myroutine( &myarray3[0][0][0], 3, 10, 10, 10 );

你要按如下方式处理:

#include <stdarg.h>
...
void myroutine( int *input_array, int num_dimens, ... ) // ... for additional arguments specifying dimension lengths
{
  va_alist ap;
  size_t *dims = malloc( num_dimens * sizeof *dims );

  va_start( ap, num_dimens );
  for ( int i = 0; i < num_dimens; i++ )
  {
    dims[i] = va_arg( ap, int ); 
  }
  va_end( ap );
  ...

然后,根据维度的数量,您可以以不同方式处理input_array:

  switch( num_dimens )
  {
    case 1:
      input_array[i] = value;
      break;

    case 2:
      input_array[i * dims[0] + j] = value;
      break;

    case 3:
      input_array[i * dims[0] * dims[1] * j * dims[1] * k ] = value;
      break;
    ...
  }
  ...
  free( dims );
}

当然,你必须弄清楚你是如何循环一维阵列而不是二维阵列与三维阵列等。正如其他人建议的那样,你最好不要创建单独的函数对于每个维度。您可以使用伪多态函数作为它们的包装器,但是您将失去类型安全的好处。

修改

指向第一个元素的指针以及数组本身:

int *ptr;

#if 1D
int myarray[10];
ptr = &myarray[0];
#else
int myarray[10][10];
ptr = &myarray[0][0];
#endif

然后打电话给

myroutine( ptr, 1, 10 );

myroutine( ptr, 2, 10, 10 );

答案 1 :(得分:1)

写两个单独的函数,每个函数处理一个案例。您希望保持编译器类型检查对您有利。无论如何,案件确实不同。要索引1D数组,需要一个int,对于2D数组,您需要两个整数和有关表宽度的信息。

您还可以将两种方法的重复逻辑提取到一个单独的函数中,但在一切正常工作后执行此操作。

答案 2 :(得分:1)

我强烈建议制作2个函数,这些函数可能会调用普通的worker函数。正确的程序设计总是比使用/滥用或多或少模糊的语言机制更好。

话虽如此,代码将无法编译,因为在2D数组的情况下,您将数组指针传递给期望指向int的指针的函数。如果您坚持这样做,请转换为void*或使该函数采用void*参数。

答案 3 :(得分:1)

您的方法不起作用,因为 myarray 会衰减到int[10],但 myarray2 会衰变为int(*)[10]。如果您确实想使用一个函数,则应使用void指针禁用类型检查:

void myroutine(void *input_array, int num_dimens)
/*             ^^^^                             */
{
   /* stuff here */
}

或者,您可以“作弊”并保留您的签名,但不应拨打myroutine(myarray2, 2),而应使用:

myroutine(myarray2[0], 2)

答案 4 :(得分:1)

这是一种处理未知维度的2D数组的方法。它使用可变长度数组(VLA) 1 语法来正确声明指向数组的指针。

void foo( int rows, int cols, int (*array2d)[cols] )
{
    int value = 1;
    for ( int i = 0; i < rows; i++ )
        for ( int j = 0; j < cols; j++ )
            array2d[i][j] = value++;
}

int main( void )
{
    // declare an array
    int myarray[5][10];

    // initialize the array
    foo( 5, 10, myarray );

    // show the array
    for ( int row = 0; row < 5; row++ )
    {
        for ( int col = 0; col < 10; col++ )
            printf( "%2d ", myarray[row][col] );
        printf( "\n" );
    }
}

1 在C99中引入了VLA,但从C11开始,编译器对VLA的支持是可选的。

答案 5 :(得分:1)

[为了便于阅读,我将10改为4并使2D阵列不对称]

int a[4];

的元素
int b[3][4];

因此,让你的函数知道2D数组,并将指针传递给它的元素以及元素的数量。

void f(int (*)[4], size_t);

并像这样称呼它

f(&a, 1);

f(b, 3);

在函数内部访问像这样的元素:

void f(int (*c)[4], size_t s)
{
  for (size_t i = 0; i < s; ++i)
  {
    for (size_t j = 0; j < 4; ++j)
    {
      printf ("c[%zu][%zu] = %d\n", i, j, c[i][j]);
    }
  }
}

并称之为:

#include <stdio.h>

void f(int (*)[4], size_t);

int main (void)
{
  int a[4] = { 1, 2, 3, 4 };
  int b[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

  printf("a:\n");
  f(&a, 1);
  printf("b:\n");
  f(b, 3); /* b decays to a pointer to its 1st element. */
}

答案 6 :(得分:0)

制作类似

的结构
struct Array1or2 {
  int *data;
  unsigned DimCount;
  // If not always width 10, add unsigned Width;
};

创建

等功能
void Array1or2_Create(struct Array1or2 *A, unsigned Dims);
void Array1or2_Destroy(struct Array1or2 *A);

// Get value with only X
int Array1or2_X(const struct Array1or2 *A, unsigned x);
// Get value with X & Y
int Array1or2_XY(const struct Array1or2 *A, unsigned x, unsigned x);

示例实现

void Array1or2_Create(struct Array1or2 *A, unsigned Dims) {
  assert(Dims >= 1 && Dims <= 2); 
  A->DimCount = Dims;
  size_t size = sizeof *(A->data);
  while (Dims > 0) size *= 10;
  A->data = malloc(size);
  assert(A->data); 
}

int Array1or2_X(const struct Array1or2 *A, unsigned x) {
  assert(x < 10); 
  return A->data[x];
}

int Array1or2_XY(const struct Array1or2 *A, unsigned x, unsigned y) {
  assert(x < 10 && y < 10); 
  if (A->DimCount < 2) return 0;
  return A->data[x + 10*y];
}