访问二维数组中的元素时出错
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 );
【讨论】:
以上是关于访问二维数组中的元素时出错的主要内容,如果未能解决你的问题,请参考以下文章