具有负索引的C中的2d数组
我正在编写一个C程序,其中需要具有负索引的2D数组(动态分配),或者索引不从零开始。因此,对于数组[i][j],行索引i应取值范围为1到3,列索引j应取值范围为-1到9 为此,我创建了以下程序,在这里变量columns_start被设置为零,所以只需移动行索引,就可以很好地工作 但是,当我为变量列_start指定除零以外的其他值时,我(从valgrind)得到一条消息,“free(array[I]);”命令无效。 因此,我的问题是:具有负索引的C中的2d数组,c,arrays,memory-management,free,C,Arrays,Memory Management,Free,我正在编写一个C程序,其中需要具有负索引的2D数组(动态分配),或者索引不从零开始。因此,对于数组[i][j],行索引i应取值范围为1到3,列索引j应取值范围为-1到9 为此,我创建了以下程序,在这里变量columns_start被设置为零,所以只需移动行索引,就可以很好地工作 但是,当我为变量列_start指定除零以外的其他值时,我(从valgrind)得到一条消息,“free(array[I]);”命令无效。 因此,我的问题是: 为什么释放我刚才分配的内存是无效的 如何修改程序以移动列索引
#include <stdio.h>
#include <stdlib.h>
main()
{
int **array, **array2;
int rows_end, rows_start, columns_end, columns_start, i, j;
rows_start = 1;
rows_end = 3;
columns_start = 0;
columns_end = 9;
array = malloc((rows_end-rows_start+1) * sizeof(int *));
for(i = 0; i <= (rows_end-rows_start); i++) {
array[i] = malloc((columns_end-columns_start+1) * sizeof(int));
}
array2 = array-rows_start; //shifting row-index
for(i = rows_start; i <= rows_end; i++) {
array2[i] = array[i-rows_start]-columns_start; //shifting column-index
}
for(i = rows_start; i <= rows_end; i++) {
for(j = columns_start; j <= columns_end; j++) {
array2[i][j] = i+j; //writing stuff into array
printf("%i %i %d\n",i, j, array2[i][j]);
}
}
for(i = 0; i <= (rows_end-rows_start); i++) {
free(array[i]);
}
free(array);
}
#包括
#包括
main()
{
整数**数组,**数组2;
int行结束,行开始,列结束,列开始,i,j;
行_start=1;
行_end=3;
列_start=0;
列_end=9;
数组=malloc((行结束行开始+1)*sizeof(int*);
对于(i=0;i据我所知,您的免费和malloc看起来不错。但是您的转换没有意义。为什么不在数组中添加一个偏移量,而不是使用数组2
:
int maxNegValue = 10;
int myNegValue = -6;
array[x][myNegValue+maxNegValue] = ...;
这样,你总是在积极的范围内
对于malloc
:您获得(maxNegValue+maxPosValue)*sizeof(…)
好的,我现在明白了,您需要免费(数组..+offset)
甚至使用移位的东西..这可能不是你想要的。如果你不需要很快的实现,我建议使用一个包含偏移量和数组的结构。然后创建一个函数,将此结构和x/y作为参数,以允许访问数组。当你移位列索引时,你会给原始索引分配新的值列数组:在
array2[i] = array[i-rows_start]-columns_start;
array2[i]和array[i=rows\u start]是同一个内存单元,因为array2是用array-rows\u start初始化的
因此,释放内存需要反向移位。请尝试以下操作:
free(array[i] + columns_start);
这样修改数组索引没有任何好处,同时会使程序逻辑复杂化并导致错误。请尝试在单循环中动态修改索引。\35; include
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[] = { -1, 41, 42, 43 };
int *b;//you will always read the data via this pointer
b = &a[1];// 1 is becoming the "zero pivot"
printf("zero: %d\n", b[0]);
printf("-1: %d\n", b[-1]);
return EXIT_SUCCESS;
}
#包括
内部主(空){
INTA[]={-1,41,42,43};
int*b;//您将始终通过此指针读取数据
b=&a[1];//1正在成为“零轴”
printf(“零:%d\n”,b[0]);
printf(“-1:%d\n”,b[-1]);
返回退出成功;
}
如果您不需要一个连续的块,那么最好使用哈希表。我不知道valgrind为什么会抱怨free
语句,但是似乎有很多指针在变戏法,所以您一开始就遇到这个问题并不奇怪我的眼睛是:
array2 = array-rows_start;
这将使array2[0]取消引用您未分配的内存。我担心偏移计算出错并遇到此问题只是时间问题
你写的一条评论
但在我的程序中,我需要很多具有所有不同起始索引的数组,所以我希望找到一个更优雅的解决方案,而不是为每个数组定义两个偏移量
我想我会把它隐藏在<代码>矩阵>代码>帮助器结构(+函数)中,这样你就不必用所有的偏移来扰乱你的代码。在某些代码>矩阵中考虑这个问题。
struct matrix; /* opaque type */
/* Allocates a matrix with the given dimensions, sample invocation might be:
*
* struct matrix *m;
* matrix_alloc( &m, -2, 14, -9, 33 );
*/
void matrix_alloc( struct matrix **m, int minRow, int maxRow, int minCol, int maxCol );
/* Releases resources allocated by the given matrix, e.g.:
*
* struct matrix *m;
* ...
* matrix_free( m );
*/
void matrix_free( struct matrix *m );
/* Get/Set the value of some elment in the matrix; takes logicaly (potentially negative)
* coordinates and translates them to zero-based coordinates internally, e.g.:
*
* struct matrix *m;
* ...
* int val = matrix_get( m, 9, -7 );
*/
int matrix_get( struct matrix *m, int row, int col );
void matrix_set( struct matrix *m, int row, int col, int val );
下面是实现的样子(这将是matrix.c
):
结构矩阵{
int minRow、maxRow、minCol、maxCol;
国际**要素;
};
void matrix_alloc(结构矩阵**m,int-minCol,int-maxCol,int-minRow,int-maxRow){
int numRows=maxRow-minRow;
int numCols=maxCol-minCol;
*m=malloc(sizeof(结构矩阵));
*elem=malloc(numRows*sizeof(*elem));
对于(int i=0;ielem[row-m->minRow][col-m->minCol];
}
无效矩阵集合(结构矩阵*m,整数列,整数行,整数值){
m->elem[row-m->minRow][col-m->minCol]=val;
}
这样,你只需要在一个中心位置正确处理一次。你程序的其余部分不必处理原始数组,而是处理struct matrix
类型。IMHO从C
生成pascal
不是一个好主意。例如,有没有可能在不消除错误的情况下减少这个测试用例,是否需要第二个和第三个循环?可能是两个malloc
步骤(对于外部和内部阵列)再加上最后的free
步骤已经足够触发valgrind警告了?嗨,谢谢你的回答。偏移量是个主意,但我的程序需要很多具有所有不同起始索引的数组,所以我希望找到一个更优雅的解决方案,而不是为每个数组定义两个偏移量。符号是right我想,因为我想把array2[1]的值赋给array[0]。比如说,我如何在不使用array2的情况下重写程序?我想你的valgrind问题已经解决了。这样你就不必删除array2
。用不同的解决方案更新了我的答案。检查array/array2的使用情况。为什么?我看不出array
在哪里移位了。只有array2
指向移位的位置<代码>数组
从未更改过..array2指向array-rows\u start。因此,array2[rowstart]==array[0]free(array[i]+columns\u start);这很有效,非常感谢。@tyz,我用你的上述评论更新了你的答案。这是我在我的(现已删除)中遗漏的内容回答这个问题,我猜OP也漏掉了。编辑允许我用一个向上的选项来代替我的反对票
struct matrix {
int minRow, maxRow, minCol, maxCol;
int **elem;
};
void matrix_alloc( struct matrix **m, int minCol, int maxCol, int minRow, int maxRow ) {
int numRows = maxRow - minRow;
int numCols = maxCol - minCol;
*m = malloc( sizeof( struct matrix ) );
*elem = malloc( numRows * sizeof( *elem ) );
for ( int i = 0; i < numRows; ++i )
*elem = malloc( numCols * sizeof( int ) );
/* setting other fields of the matrix omitted for brevity */
}
void matrix_free( struct matrix *m ) {
/* omitted for brevity */
}
int matrix_get( struct matrix *m, int col, int row ) {
return m->elem[row - m->minRow][col - m->minCol];
}
void matrix_set( struct matrix *m, int col, int row, int val ) {
m->elem[row - m->minRow][col - m->minCol] = val;
}