Calloc用于C中具有负索引的数组数组

我有一个带负索引的数组数组。 它是一个具有实际尺寸[dim_y + 40] [dim_x + 40]的数组,但是用户使用的数据类似于维度[dim_y] [dim_x]。 首先,我有全局,已经定义了维度dim_x,dim_y,所以我有这个

int map_boundaries[dim_y + 40][dim_x + 40]; int (*map)[dim_x+40] = (int(*)[dim_x+40])&map_boundaries[20][20]; 

它工作正常。 现在我需要维度dim_y和dim_x是可变的,这意味着我希望数组’map’没有固定大小但是动态,我需要从用户读取dim_y,dim_x和数组’map’是全球性的,所以我有

 int **map_boundaries; 

我在main()使用calloc

 map_boundaries = (int **)calloc(dim_y + 40,sizeof(int*)); for(i = 0; i < dim_y + 40; i++){ map_boundaries[i] = (int *)calloc(dim_x + 40,sizeof(int)); } 

,但我不知道如何申报第二行

为了更好地理解边界,我在第2条评论中发布了这些内容: http : //everything2.com/title/Negative+array+indexing

我会分配一个数组:

 int* storage = calloc((dim_x + 40) * (dim_y + 40), sizeof(int)); 

然后我会在一个不透明的结构中将它返回给用户,如下所示:

 struct map { int* storage; size_t dim_x; size_t dim_y; }; 

然后我会为用户定义一个索引函数:

 int* get_cell(struct map* m, x, y) { return &m->storage[(x + 20) + (m->dim_x + 40) * (y + 20)]; } 

如果用户想要在一行中读/写多个元素,也许可以获得整行:

 int* get_row(struct map* m, y) { return get_cell(m, 0, y); } size_t get_row_size(struct map* m) { return m->dim_x; } 

由于您希望在运行时确定尺寸,因此您需要在任何情况下进行运行时索引计算。

这是我的代码版本。 int **map值是用户和库用于访问数据的内容。 Matrix结构封装了有关数组的所有信息,包括用于初始化map的成员。 代码设置大小,分配和初始化结构,然后初始化数组,然后像用户那样使用它,就像库一样。 最后,释放分配的内存。

实际上,您可能希望将其拆分为多个单独的函数。

资料来源: 2da.c

 #include  #include  #include  #include "stderr.h" typedef struct Matrix { int *map_base; int **map_rows; int x_dim; int y_dim; int extra; int **map; } Matrix; int main(void) { Matrix m; int x_dim = 8; int y_dim = 6; int extra = 5; /* Allocation */ m.extra = extra; m.x_dim = x_dim; m.y_dim = y_dim; int x_cells = x_dim + 2 * extra; int y_cells = y_dim + 2 * extra; m.map_base = calloc(x_cells * y_cells, sizeof(**m.map)); if (m.map_base == 0) err_syserr("Failed to allocate %zu bytes memory\n", x_cells * y_cells * sizeof(**m.map)); m.map_rows = calloc(x_cells, sizeof(*m.map)); if (m.map_rows == 0) err_syserr("Failed to allocate %zu bytes memory\n", x_cells * sizeof(*m.map)); //printf("Map base: 0x%.8" PRIXPTR "\n", (uintptr_t)m.map_base); //printf("Map rows: 0x%.8" PRIXPTR "\n", (uintptr_t)m.map_rows); for (int i = 0; i < x_cells; i++) { m.map_rows[i] = &m.map_base[i * y_cells + extra]; //printf("Row[%2d] 0x%.8" PRIXPTR "\n", i, (uintptr_t)m.map_rows[i]); } m.map = &m.map_rows[extra]; int **map = m.map; //printf("Map: 0x%.8" PRIXPTR "\n", (uintptr_t)map); /* Initialization */ int x_min = -extra; int y_min = -extra; int x_max = x_dim + extra; int y_max = y_dim + extra; printf("Initialization:\n"); for (int i = x_min; i < x_max; i++) { for (int j = y_min; j < y_max; j++) { map[i][j] = i * 100 + j; //printf("[%2d,%2d] = %4d\n", i, j, map[i][j]); } } printf("User view:\n"); for (int i = 0; i < x_dim; i++) { for (int j = 0; j < y_dim; j++) printf("[%2d,%2d] = %4d\n", i, j, map[i][j]); } printf("Library view:\n"); for (int i = x_min; i < x_max; i++) { for (int j = y_min; j < y_max; j++) printf("[%2d,%2d] = %4d\n", i, j, map[i][j]); } /* Deallocation */ free(m.map_base); free(m.map_rows); return 0; } 

示例输出

当在Mac OS X 10.9.5上使用GCC 4.9.1在valgrind 3.10.0下运行时,我得到了以下输出。 "stderr.h"标题位于$HOME/inc并声明为err_syserr() ,而libjl.a位于$HOME/lib/64并提供err_syserr()的实现,该函数报告给定的错误消息和由errno和退出标识的errno 。 我这次懒得在这个程序中编写代码。 (在SO中搜索'[c] user:15168 err_syserr'以查找使用信号量保护共享内存段不起作用 ,它具有基本相同的代码。我没有在此答案的代码中调用err_setarg0() 。)

 $ gcc -O3 -g -I/Users/jleffler/inc -std=c11 -Wall -Wextra -Wmissing-prototypes \ > -Wstrict-prototypes -Wold-style-definition -Werror 2da.c -o 2da \ > -L/Users/jleffler/lib/64 -ljl $ valgrind ./2da ==26293== Memcheck, a memory error detector ==26293== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==26293== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info ==26293== Command: 2da ==26293== Initialization: User view: [ 0, 0] = 0 [ 0, 1] = 1 [ 0, 2] = 2 [ 0, 3] = 3 [ 0, 4] = 4 [ 0, 5] = 5 [ 1, 0] = 100 [ 1, 1] = 101 [ 1, 2] = 102 [ 1, 3] = 103 [ 1, 4] = 104 [ 1, 5] = 105 [ 2, 0] = 200 [ 2, 1] = 201 [ 2, 2] = 202 [ 2, 3] = 203 [ 2, 4] = 204 [ 2, 5] = 205 [ 3, 0] = 300 [ 3, 1] = 301 [ 3, 2] = 302 [ 3, 3] = 303 [ 3, 4] = 304 [ 3, 5] = 305 [ 4, 0] = 400 [ 4, 1] = 401 [ 4, 2] = 402 [ 4, 3] = 403 [ 4, 4] = 404 [ 4, 5] = 405 [ 5, 0] = 500 [ 5, 1] = 501 [ 5, 2] = 502 [ 5, 3] = 503 [ 5, 4] = 504 [ 5, 5] = 505 [ 6, 0] = 600 [ 6, 1] = 601 [ 6, 2] = 602 [ 6, 3] = 603 [ 6, 4] = 604 [ 6, 5] = 605 [ 7, 0] = 700 [ 7, 1] = 701 [ 7, 2] = 702 [ 7, 3] = 703 [ 7, 4] = 704 [ 7, 5] = 705 Library view: [-5,-5] = -505 [-5,-4] = -504 [-5,-3] = -503 [-5,-2] = -502 [-5,-1] = -501 [-5, 0] = -500 [-5, 1] = -499 [-5, 2] = -498 [-5, 3] = -497 [-5, 4] = -496 [-5, 5] = -495 [-5, 6] = -494 [-5, 7] = -493 [-5, 8] = -492 [-5, 9] = -491 [-5,10] = -490 [-4,-5] = -405 [-4,-4] = -404 [-4,-3] = -403 [-4,-2] = -402 [-4,-1] = -401 [-4, 0] = -400 [-4, 1] = -399 [-4, 2] = -398 [-4, 3] = -397 [-4, 4] = -396 [-4, 5] = -395 [-4, 6] = -394 [-4, 7] = -393 [-4, 8] = -392 [-4, 9] = -391 [-4,10] = -390 [-3,-5] = -305 [-3,-4] = -304 [-3,-3] = -303 [-3,-2] = -302 [-3,-1] = -301 [-3, 0] = -300 [-3, 1] = -299 [-3, 2] = -298 [-3, 3] = -297 [-3, 4] = -296 [-3, 5] = -295 [-3, 6] = -294 [-3, 7] = -293 [-3, 8] = -292 [-3, 9] = -291 [-3,10] = -290 [-2,-5] = -205 [-2,-4] = -204 [-2,-3] = -203 [-2,-2] = -202 [-2,-1] = -201 [-2, 0] = -200 [-2, 1] = -199 [-2, 2] = -198 [-2, 3] = -197 [-2, 4] = -196 [-2, 5] = -195 [-2, 6] = -194 [-2, 7] = -193 [-2, 8] = -192 [-2, 9] = -191 [-2,10] = -190 [-1,-5] = -105 [-1,-4] = -104 [-1,-3] = -103 [-1,-2] = -102 [-1,-1] = -101 [-1, 0] = -100 [-1, 1] = -99 [-1, 2] = -98 [-1, 3] = -97 [-1, 4] = -96 [-1, 5] = -95 [-1, 6] = -94 [-1, 7] = -93 [-1, 8] = -92 [-1, 9] = -91 [-1,10] = -90 [ 0,-5] = -5 [ 0,-4] = -4 [ 0,-3] = -3 [ 0,-2] = -2 [ 0,-1] = -1 [ 0, 0] = 0 [ 0, 1] = 1 [ 0, 2] = 2 [ 0, 3] = 3 [ 0, 4] = 4 [ 0, 5] = 5 [ 0, 6] = 6 [ 0, 7] = 7 [ 0, 8] = 8 [ 0, 9] = 9 [ 0,10] = 10 [ 1,-5] = 95 [ 1,-4] = 96 [ 1,-3] = 97 [ 1,-2] = 98 [ 1,-1] = 99 [ 1, 0] = 100 [ 1, 1] = 101 [ 1, 2] = 102 [ 1, 3] = 103 [ 1, 4] = 104 [ 1, 5] = 105 [ 1, 6] = 106 [ 1, 7] = 107 [ 1, 8] = 108 [ 1, 9] = 109 [ 1,10] = 110 [ 2,-5] = 195 [ 2,-4] = 196 [ 2,-3] = 197 [ 2,-2] = 198 [ 2,-1] = 199 [ 2, 0] = 200 [ 2, 1] = 201 [ 2, 2] = 202 [ 2, 3] = 203 [ 2, 4] = 204 [ 2, 5] = 205 [ 2, 6] = 206 [ 2, 7] = 207 [ 2, 8] = 208 [ 2, 9] = 209 [ 2,10] = 210 [ 3,-5] = 295 [ 3,-4] = 296 [ 3,-3] = 297 [ 3,-2] = 298 [ 3,-1] = 299 [ 3, 0] = 300 [ 3, 1] = 301 [ 3, 2] = 302 [ 3, 3] = 303 [ 3, 4] = 304 [ 3, 5] = 305 [ 3, 6] = 306 [ 3, 7] = 307 [ 3, 8] = 308 [ 3, 9] = 309 [ 3,10] = 310 [ 4,-5] = 395 [ 4,-4] = 396 [ 4,-3] = 397 [ 4,-2] = 398 [ 4,-1] = 399 [ 4, 0] = 400 [ 4, 1] = 401 [ 4, 2] = 402 [ 4, 3] = 403 [ 4, 4] = 404 [ 4, 5] = 405 [ 4, 6] = 406 [ 4, 7] = 407 [ 4, 8] = 408 [ 4, 9] = 409 [ 4,10] = 410 [ 5,-5] = 495 [ 5,-4] = 496 [ 5,-3] = 497 [ 5,-2] = 498 [ 5,-1] = 499 [ 5, 0] = 500 [ 5, 1] = 501 [ 5, 2] = 502 [ 5, 3] = 503 [ 5, 4] = 504 [ 5, 5] = 505 [ 5, 6] = 506 [ 5, 7] = 507 [ 5, 8] = 508 [ 5, 9] = 509 [ 5,10] = 510 [ 6,-5] = 595 [ 6,-4] = 596 [ 6,-3] = 597 [ 6,-2] = 598 [ 6,-1] = 599 [ 6, 0] = 600 [ 6, 1] = 601 [ 6, 2] = 602 [ 6, 3] = 603 [ 6, 4] = 604 [ 6, 5] = 605 [ 6, 6] = 606 [ 6, 7] = 607 [ 6, 8] = 608 [ 6, 9] = 609 [ 6,10] = 610 [ 7,-5] = 695 [ 7,-4] = 696 [ 7,-3] = 697 [ 7,-2] = 698 [ 7,-1] = 699 [ 7, 0] = 700 [ 7, 1] = 701 [ 7, 2] = 702 [ 7, 3] = 703 [ 7, 4] = 704 [ 7, 5] = 705 [ 7, 6] = 706 [ 7, 7] = 707 [ 7, 8] = 708 [ 7, 9] = 709 [ 7,10] = 710 [ 8,-5] = 795 [ 8,-4] = 796 [ 8,-3] = 797 [ 8,-2] = 798 [ 8,-1] = 799 [ 8, 0] = 800 [ 8, 1] = 801 [ 8, 2] = 802 [ 8, 3] = 803 [ 8, 4] = 804 [ 8, 5] = 805 [ 8, 6] = 806 [ 8, 7] = 807 [ 8, 8] = 808 [ 8, 9] = 809 [ 8,10] = 810 [ 9,-5] = 895 [ 9,-4] = 896 [ 9,-3] = 897 [ 9,-2] = 898 [ 9,-1] = 899 [ 9, 0] = 900 [ 9, 1] = 901 [ 9, 2] = 902 [ 9, 3] = 903 [ 9, 4] = 904 [ 9, 5] = 905 [ 9, 6] = 906 [ 9, 7] = 907 [ 9, 8] = 908 [ 9, 9] = 909 [ 9,10] = 910 [10,-5] = 995 [10,-4] = 996 [10,-3] = 997 [10,-2] = 998 [10,-1] = 999 [10, 0] = 1000 [10, 1] = 1001 [10, 2] = 1002 [10, 3] = 1003 [10, 4] = 1004 [10, 5] = 1005 [10, 6] = 1006 [10, 7] = 1007 [10, 8] = 1008 [10, 9] = 1009 [10,10] = 1010 [11,-5] = 1095 [11,-4] = 1096 [11,-3] = 1097 [11,-2] = 1098 [11,-1] = 1099 [11, 0] = 1100 [11, 1] = 1101 [11, 2] = 1102 [11, 3] = 1103 [11, 4] = 1104 [11, 5] = 1105 [11, 6] = 1106 [11, 7] = 1107 [11, 8] = 1108 [11, 9] = 1109 [11,10] = 1110 [12,-5] = 1195 [12,-4] = 1196 [12,-3] = 1197 [12,-2] = 1198 [12,-1] = 1199 [12, 0] = 1200 [12, 1] = 1201 [12, 2] = 1202 [12, 3] = 1203 [12, 4] = 1204 [12, 5] = 1205 [12, 6] = 1206 [12, 7] = 1207 [12, 8] = 1208 [12, 9] = 1209 [12,10] = 1210 ==26293== ==26293== HEAP SUMMARY: ==26293== in use at exit: 29,341 bytes in 374 blocks ==26293== total heap usage: 452 allocs, 78 frees, 36,581 bytes allocated ==26293== ==26293== LEAK SUMMARY: ==26293== definitely lost: 0 bytes in 0 blocks ==26293== indirectly lost: 0 bytes in 0 blocks ==26293== possibly lost: 0 bytes in 0 blocks ==26293== still reachable: 4,096 bytes in 1 blocks ==26293== suppressed: 25,245 bytes in 373 blocks ==26293== Rerun with --leak-check=full to see details of leaked memory ==26293== ==26293== For counts of detected and suppressed errors, rerun with: -v ==26293== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) $ 

'仍然可达'块是stdout的缓冲区; 如果我包括fclose(stdout); 在从main()返回之前,它会去。 Mac OS X运行时库也分配了大量内存,但在抑制信息中标识了该用法。


评论和回应

我在2行中看到了整个初始化。 但这不是初始化的问题; 问题是在每一帧中都会改变地图的值。 所以我只需要一个直接指向“边界地图”的“地图”。 map[0][0]boundaries_map[20][20] ,依此类推。 我试图声明全局**map ,然后将我的第二行写入main,但是我收到有关强制转换的错误。 (*map)[dim_x+40]这是**map不是吗?

我不确定我完全理解你所追求的是什么,这是这个反应需要很长时间的一个原因。

您不能拥有VLA的全局变量; 它们只能在函数中分配,可以作为局部变量在堆栈中分配,也可以通过malloc()等分配在堆上。 我展示的原始代码允许您通过全局变量定义一个数组,一个双指针,可以从任何可以读取双指针的代码访问。

以下代码可被视为构建VLA的练习。 它使用malloc()创建一个VLA,记录它在指向VLA的指针中的位置。 这可以传递给函数,就像可以传递基于堆栈的VLA一样。 该代码在Mac OS X 10.9.5上的GCC 4.9.1下完全编译:

 $ gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Werror \ > 2dv.c -o 2dv 

根据valgrind它运行干净,无泄漏。

资料来源: 2dv.c

 #include  #include  static void dump_vla_1(int x_size, int y_size, int vla[x_size][y_size]); static void dump_vla_2(int x_min, int y_min, int x_size, int y_size, int vla[x_size][y_size]); static void dump_vla_3(int x_min, int x_max, int y_min, int y_max, int x_size, int y_size, int vla[x_size][y_size]); int main(void) { int extra = 3; int x_base = 5; int y_base = 4; int x_size = x_base + 2 * extra; int y_size = y_base + 2 * extra; int (*vla)[x_size][y_size] = calloc(x_size * y_size, sizeof(int)); for (int i = 0; i < x_size; i++) for (int j = 0; j < y_size; j++) (*vla)[i][j] = (i + 1) * 100 + (j + 1); for (int i = 0; i < x_size; i++) { for (int j = 0; j < y_size; j++) printf(" %4d", (*vla)[i][j]); putchar('\n'); } dump_vla_1(x_size, y_size, *vla); dump_vla_2(0, 0, x_size, y_size, *vla); /* Harsh cast! */ int (*vla_2)[x_size][y_size] = (int (*)[x_size][y_size])&(*vla)[extra][extra]; dump_vla_2(-extra, -extra, x_size, y_size, *vla_2); dump_vla_3(-extra, x_size - extra, -extra, y_size - extra, x_size, y_size, *vla_2); dump_vla_3(0, x_base, 0, y_base, x_size, y_size, *vla_2); free(vla); return 0; } static void dump_vla_1(int x_size, int y_size, int vla[x_size][y_size]) { printf("Matrix %dx%d\n", x_size, y_size); for (int i = 0; i < x_size; i++) { for (int j = 0; j < y_size; j++) printf(" %4d", vla[i][j]); putchar('\n'); } } static void dump_vla_2(int x_min, int y_min, int x_size, int y_size, int vla[x_size][y_size]) { printf("Matrix %dx%d (%d..%d, %d..%d)\n", x_size, y_size, x_min, x_min + x_size - 1, y_min, y_min + y_size - 1); for (int i = x_min; i < x_min + x_size; i++) { for (int j = y_min; j < y_min + y_size; j++) printf(" %4d", vla[i][j]); putchar('\n'); } } static void dump_vla_3(int x_min, int x_max, int y_min, int y_max, int x_size, int y_size, int vla[x_size][y_size]) { printf("Matrix %dx%d (%d..%d, %d..%d)\n", x_size, y_size, x_min, x_max, y_min, y_max); for (int i = x_min; i < x_max; i++) { for (int j = y_min; j < y_max; j++) printf(" %4d", vla[i][j]); putchar('\n'); } } 

注意使用*vla*vla_2将VLA传递给函数。 由于vlavla_2变量是指向VLA的指针,因此*vla 函数所期望的VLA。

输出:

  101 102 103 104 105 106 107 108 109 110 201 202 203 204 205 206 207 208 209 210 301 302 303 304 305 306 307 308 309 310 401 402 403 404 405 406 407 408 409 410 501 502 503 504 505 506 507 508 509 510 601 602 603 604 605 606 607 608 609 610 701 702 703 704 705 706 707 708 709 710 801 802 803 804 805 806 807 808 809 810 901 902 903 904 905 906 907 908 909 910 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 Matrix 11x10 101 102 103 104 105 106 107 108 109 110 201 202 203 204 205 206 207 208 209 210 301 302 303 304 305 306 307 308 309 310 401 402 403 404 405 406 407 408 409 410 501 502 503 504 505 506 507 508 509 510 601 602 603 604 605 606 607 608 609 610 701 702 703 704 705 706 707 708 709 710 801 802 803 804 805 806 807 808 809 810 901 902 903 904 905 906 907 908 909 910 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 Matrix 11x10 (0..10, 0..9) 101 102 103 104 105 106 107 108 109 110 201 202 203 204 205 206 207 208 209 210 301 302 303 304 305 306 307 308 309 310 401 402 403 404 405 406 407 408 409 410 501 502 503 504 505 506 507 508 509 510 601 602 603 604 605 606 607 608 609 610 701 702 703 704 705 706 707 708 709 710 801 802 803 804 805 806 807 808 809 810 901 902 903 904 905 906 907 908 909 910 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 Matrix 11x10 (-3..7, -3..6) 101 102 103 104 105 106 107 108 109 110 201 202 203 204 205 206 207 208 209 210 301 302 303 304 305 306 307 308 309 310 401 402 403 404 405 406 407 408 409 410 501 502 503 504 505 506 507 508 509 510 601 602 603 604 605 606 607 608 609 610 701 702 703 704 705 706 707 708 709 710 801 802 803 804 805 806 807 808 809 810 901 902 903 904 905 906 907 908 909 910 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 Matrix 11x10 (-3..8, -3..7) 101 102 103 104 105 106 107 108 109 110 201 202 203 204 205 206 207 208 209 210 301 302 303 304 305 306 307 308 309 310 401 402 403 404 405 406 407 408 409 410 501 502 503 504 505 506 507 508 509 510 601 602 603 604 605 606 607 608 609 610 701 702 703 704 705 706 707 708 709 710 801 802 803 804 805 806 807 808 809 810 901 902 903 904 905 906 907 908 909 910 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 Matrix 11x10 (0..5, 0..4) 404 405 406 407 504 505 506 507 604 605 606 607 704 705 706 707 804 805 806 807