我正在编写一个C程序,我需要带有负索引的2D数组(动态分配)或索引不从零开始。因此对于数组[i] [j],行索引i应该取值来自例如1至3和列索引j应取值来自例如-1到9。
为此,我创建了以下程序,这里变量columns_start设置为零,所以只是行索引被移位了,这非常好。
但是当我为变量columns_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);
}
答案 0 :(得分:5)
当您移动列索引时,可以为原始列数组指定新值:in
array2[i] = array[i-rows_start]-columns_start;
array2 [i]和array [i = rows_start]是与array2用array-rows_start初始化相同的内存单元。
因此,内存的释放需要反向移位。请尝试以下方法:
free(array[i] + columns_start);
恕我直言,这种数组索引的修改没有任何好处,同时使程序逻辑复杂化并导致错误。尝试在单循环中动态修改索引。
答案 1 :(得分:2)
#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;
}
如果你不需要一个连续的块,那么你最好使用哈希表。
答案 2 :(得分:1)
据我所知,你的free和malloc看起来很棒。但是你的转变没有意义。为什么不在array
添加偏移,而不是使用array2
:
int maxNegValue = 10;
int myNegValue = -6;
array[x][myNegValue+maxNegValue] = ...;
这样,你总是在积极的范围内。
对于malloc
:您获得了(maxNegValue + maxPosValue) * sizeof(...)
好的,我现在明白了,即使使用你的移动东西你也需要free(array.. + offset);
..这可能不是你想要的。如果您不需要非常快速的实现,我建议使用包含偏移量和数组的结构。然后创建一个具有此结构和x / y作为参数的函数,以允许访问该数组。
答案 3 :(得分:0)
我不知道为什么valgrind会抱怨free
语句,但似乎有很多指针杂耍正在发生,因此我首先得到这个问题并不让我感到惊讶。例如,引起我注意的一件事是:
array2 = array-rows_start;
这将使你没有分配的array2 [0]解引用内存。我担心只是时间问题,直到你得到偏移计算错误并遇到这个问题。
你写的一条评论
但是我的程序我需要很多具有所有不同开始索引的数组,所以我希望找到一个更优雅的解决方案,而不是为每个数组定义两个偏移。
我想我会在matrix
辅助结构(+函数)中隐藏所有这些,这样您就不必使用所有偏移来混淆代码。在一些matrix.h
标题中考虑这一点:
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
):
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;
}
这样你只需要在中央位置获得一次这个东西。程序的其余部分不必处理原始数组,而是处理struct matrix
类型。