指向二维数组的指针

时间:2013-12-24 14:45:52

标签: c arrays pointers

请,我是C编程的新手,请帮助我。以下代码中有一些错误? 基本上,我们如何处理指向二维数组的指针......

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

int* max5(int** p,int r,int c)
{

/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/

}

int main()

{

    int rows,coloumns;
    printf("Enter the number of rows and coloumns separated by a space\n");
    scanf("%d %d",&rows,&coloumns);
    int **ptr;

    ptr=(int**)malloc(sizeof(int*)*rows);
    int i,j;
    for(i=0;i<rows;i++)
    {
        for(j=0;j<coloumns;j++)
        {
            scanf("%d",*(ptr+i)+j);
            printf("%d\n",*(*(ptr+i)+j));
        }
    }
    free(ptr);
    return 0;
}

4 个答案:

答案 0 :(得分:1)

在C中,2D数组只是具有不同索引的常规数组。所以,你有两个选择:

  1. 分配数组并将其编入索引:array[I*n+j]
  2. 分配一个数组数组(这是你似乎要做的事情)
  3. 您可以按相关帖子中显示的方式实现第二个:allocate matrix in C

答案 1 :(得分:1)

动态分配2D阵列可以通过多种方式完成。

假设你有一个支持可变长度数组的C99编译器或C2011编译器,这很容易:

int rows, columns;
...
scanf("%d %d",&rows,&columns);
int array[rows][columns];

array是一个可变长度数组(VLA),意味着它的维度是在运行时建立的。要将其传递给另一个函数,原型就是

int *max5( int rows, int columns, int arr[rows][columns] ) { ... }

也可以写成

int *max5( int rows, int columns, int (*arr)[columns] ) { ... }

我将进入下面的第二个表格。请注意,在VLA声明中使用它们之前,必须声明rowscolumns

您可以将其称为

int *maxarr = max5( rows, columns, array );

这种方法的优点是:a)它很容易,并且b)array的内存被连续分配(即,作为单个连续的内存块),并在您退出它的封闭后立即释放范围;没有必要手动free它。这种方法的缺点rowscolumns不能任意大,你不能使用常规初始化语法初始化数组(即你不能写int array[rows][columns] = { ... };),你不能在文件范围定义VLA(即作为全局变量)。还有一个问题是VLA支持总是有点不稳定,2011标准现在使它们成为可选项,所以不能保证它们在任何地方都会得到支持。

如果rowscolumns非常大,或者由于某些其他原因你想从堆中分配这个内存,那只会稍微复杂一些:

int rows, columns;
...
scanf("%d %d", rows, columns);
int (*array)[columns] = malloc( sizeof *array * rows );

在此版本中,array是一个指针,指向int的N元素数组(其中N == columns),我们{{ 1}}空间来容纳M个这样的数组(其中M == malloc)。同样,这利用了VLA语法,但是我们不是从堆栈帧分配内存,而是从堆中分配它。与第一种方法一样,内存是连续分配的。你可以像任何其他数组一样索引它:

rows

完成数组后,您可以将其释放为

array[i][j] = x;

free( array ); 的原型将是

max5

看起来很熟悉?这是我们之前通过2D VLA时使用的第二个版本。

除非它是int *max5( int rows, int columns, int (*arr)[columns] ) { ... } 或一元sizeof运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则表达式为“N-element array of &“将转换为”指向T的指针“的表达式,表达式的值将是数组中第一个元素的地址。

在我们将T声明为2D VLA的第一种情况下,当您致电

array

表达式int *maxarr = max5( rows, columns, array ); 从类型“array - rows的元素数组 - columns的元素数组”转换为“指向int的指针 - 元素数组columns“,所以int接收的是指针值,而不是数组。恰好在函数参数声明的上下文中,max5T a[N]都被解释为T a[]; IOW,这三个都声明T *a作为指向a的指针。

因此,两者

T

int *max5( int rows, int columns, int arr[rows][columns] ) { ... }

int *max5( int rows, int columns, int (*arr)[columns] ) { ... } 声明为指向数组的指针,而不是2D数组。同样,两者都返回一个简单的arr,而不是int *的数组。这样做的原因是简单的;如果你使用

返回一个子数组
int

表达式return arr[i]; 的类型为“arr[i] - 元素数组columns”;根据上述规则,该表达式将转换为int类型。 C不允许您将数组对象作为数组返回,数组表达式也不能作为赋值的目标。

现在,如果您使用的是C89编译器或不支持VLA的C2011编译器,该怎么办?在这种情况下,您需要以零散的方式分配内存,如下所示:

int *

您的int rows, columns; int **array; ... scanf("%d %d", rows, columns); array = malloc( sizeof *array * rows ); if ( array ) { int i; for ( i = 0; i < rows; i++ ) { array[i] = malloc( sizeof *array[i] * columns ); } } 原型现在

max5

你不再处理数组或指向数组的指针了;你正在处理一个双指针,这与指向二维数组的指针不同。您仍然可以将其下标,就好像它是一个2D数组

int *max5( int rows, int columns, int **arr );

不是一个数组对象本身。

最重要的是要确保内存不是连续的;行可能在内存中不相邻,因此想要尝试使用指针向下走行,如下所示:

arr[i][j] = x;

对于分段分配的数组,这种算法不起作用。

此外,由于内存是零散分配的,因此需要逐个释放:

int (*p)[columns] = arr;
while ( some_condition )
  p++; // sets p to point to the next row

希望有所帮助。

答案 2 :(得分:0)

此代码可以解决您的问题:

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

int* max5(int** p,int r,int c)
{

/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/

}

int main()

{

    int rows,coloumns;
    printf("Enter the number of rows and coloumns separated by a space\n");
    scanf("%d %d",&rows,&coloumns);
    int **ptr;
    int i,j;

    ptr=(int**)malloc(sizeof(int*)*rows);
    for(j=0;j<coloumns;j++)
    {
        *(ptr+j) = (int *)malloc(sizeof(int)*coloumns);
    }

    for(i=0;i<rows;i++)
    {
        for(j=0;j<coloumns;j++)
        {
            scanf("%d",*(ptr+i)+j);
           //*(*(ptr+j)+i) = i+j;
            printf("%d\n",*(*(ptr+i)+j));
        }
    }
    free(ptr);
    return 0;
}
实际上你忘记为列分配内存了!

答案 3 :(得分:-1)

您可以通过正确定义类型在C中分配2D数组:

int (*ptr)[coloumns] = calloc(sizeof(int) , rows * coloumns);

然后您可以通过ptr[i][j]解决此问题。如果你的数组确实需要超出分配它的范围并且相当小,那么你也可以在堆栈上分配它

int ptr[rows][coloumns];
memset(ptr, 0, sizeof(ptr));

您尝试分配的是指针数组int (*)[coloumns]int **的类型不同,尽管它们都可以通过使用索引运算符[i][j]来解决。后者是一个复杂得多的数据结构,容易出现更多错误。除非你需要可变的行大小,否则我会反对它。