具有负索引的C中的2d数组

具有负索引的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]);”命令无效。 因此,我的问题是: 为什么释放我刚才分配的内存是无效的 如何修改程序以移动列索引

我正在编写一个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;
    }