访问二维数组中的元素时出错

Posted

技术标签:

【中文标题】访问二维数组中的元素时出错【英文标题】:Error when accessing elements in a 2d array 【发布时间】:2018-09-04 23:16:06 【问题描述】:

我正在尝试为二维数组动态分配内存,然后访问该数组。我收到以下错误: 错误:下标值既不是数组也不是指针也不是向量

    int *student; //int student[2][5]
    int main() 
       student= (int*)malloc(10*sizeof(int));
       student[0][1] = 10; //error
       printf("student %d \n",student[0][1]); //error
       return 0;
   

【问题讨论】:

在什么方面是二维的? 【参考方案1】:

二维数组是指向另一个数组的指针,因此当您声明学生时,它需要是int ** 类型。

初始化student时,首先需要为外部指针分配内存,外部指针将指向内部数组。然后为内部数组分配内存。

  int **student; //int student[2][5]
  int main() 
   student = (int**)malloc(2 * sizeof(int *));
   student[0] = (int *)malloc(5 * sizeof(int));
   student[0][1] = 10; //error
   printf("student %d \n",student[0][1]); //error
   return 0;
  

【讨论】:

这是一种方法——另一种是将指针声明为指向子数组类型的指针,即int (*student)[5] = malloc(2 * 5 * sizeof(int)); @LeeDanielCrocker 我试图让 OP 分解数组内存布局。但是你的方式肯定更简洁更短。 这两种方法有不同的内存布局。只是认为 OP 应该知道 C 中有两种完全不同的二维数组。 在 C 中不仅有至少两种不同的方法可以实现二维数组,而且应该不鼓励使用指针到指针的方法。它是低效的(更多的内存查找,以及可能破坏处理器前瞻优化的内存查找)。 Lee Daniel Crocker 展示的可变长度数组方法应该受到青睐,或者,如果针对可能不可用的 C 实现,则可以使用手动计算索引为一维数组 (row*ColumnSize+column)。【参考方案2】:

有几种方法可以做到这一点:

如果您知道在编译时需要多大的维度,并且希望行在内存中是连续的,请执行以下操作:

#define ROWS 2
#define COLUMNS 5
...
int (*student)[COLUMNS] = malloc( sizeof *student * ROWS );
...
student[i][j] = some_value;

如果您在编译时不知道维度需要多大,并且希望行在内存中是连续的,并且您的 C 版本支持可变长度数组语法(C99 或更高版本):

size_t rows;
size_t columns;

// get rows and columns somehow

int (*student)[columns] = malloc( sizeof *student * rows ); 
...
student[i][j] = some_value;

严格来说,这将调用未定义的行为,因为 VLA 上的 sizeof 是在运行时评估的,而 student 尚未初始化为指向任何有意义的地方。但是,我和其他人认为这是语言标准措辞的一个弱点,而且我从来没有遇到过这种不按预期工作的情况。但是,请注意,这并不能保证始终在任何地方工作。

如果您不知道在编译时需要多大的维度,并且您需要行在内存中是连续的,并且您没有可用的可变长度数组:

size_t rows; 
size_t columns;

// get rows and columns;

int *student = malloc( sizeof *student * rows * columns );

是的,这是一个一维数组;您必须将“行”和“列”映射到这个一维结构上:

student[i * ROWS + j] = some_value;

如果您不知道在编译时需要多大的维度,并且您不在乎行是否连续,您可以这样做:

size_t rows;
size_t columns;

// get rows and columns;

int **student = malloc( sizeof *student * rows );
if ( student )

  for ( size_t i = 0; i < rows; i++ )
  
    student[i] = malloc( sizeof *student[i] * columns );
  

...
student[i][j] = some_value;

对于前三种方法,清理很容易:

free( student );

对于最后一种方法,您必须单独释放每个“行”:

for ( size_t i = 0; i < rows; i++ )
  free( student[i] );
free( student );

【讨论】:

以上是关于访问二维数组中的元素时出错的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 C++ 中的指针访问二维数组的元素吗?

如何使用指针表达式访问 C 中的二维数组的元素?

C中的二维数组和指针 - 如何访问元素?

在 Go 中访问二维数组中的相邻元素的最有效方法是啥?

将二维字符串数组传递给函数时出错 (C++)

是否可以使用负索引访问二维数组?