C中的2d数组,负指数

时间:2011-08-09 08:28:20

标签: c arrays memory-management free

我正在编写一个C程序,我需要带有负索引的2D数组(动态分配)或索引不从零开始。因此对于数组[i] [j],行索引i应该取值来自例如1至3和列索引j应取值来自例如-1到9。

为此,我创建了以下程序,这里变量columns_start设置为零,所以只是行索引被移位了,这非常好。

但是当我为变量columns_start分配除零以外的其他值时,我得到消息(来自valgrind)命令“free(array [i]);”是无效的。 所以我的问题是:

  1. 为什么释放我刚才分配的内存是无效的?
  2. 如何修改程序以转移列索引?
  3. 感谢您的帮助。

    #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);
    
    }
    

4 个答案:

答案 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类型。