Calloc for array array with negative index in C

I have an array array with a negative index. This is an array that has real dimensions [dim_y + 40] [dim_x + 40], but the user uses the array as if it had dimensions [dim_y] [dim_x]. At first I had a global one and already defined the sizes dim_x, dim_y, so I had this

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

Everything went perfectly. Now I need the dim_y and dim_x sizes to be variable, and with this I mean that I want the map array not to have a fixed size, but dynamic, I need to read dim_y, dim_x from the user and the map array, to be global so i

 int **map_boundaries; 

and I use calloc in main()

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

but i don't know how to declare the second line

For a better understanding of the boundaries, I did what is published in the second comment here: http://everything2.com/title/Negative+array+indexing

0
c arrays declare calloc global
Oct 14 '14 at 0:00
source share
2 answers

I would allocate one array:

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

Then I would return it to the user in an opaque structure, for example:

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

Then I would define an indexing function for the user:

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

And, perhaps, to get the whole line if the user wants to read / write several elements in one line:

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

Since you want measurements to be determined at runtime, you will need to perform runtime index calculations anyway.

0
Oct. 14 '14 at 1:42 on
source share
โ€” -

Here is my version of the code. The value of int **map is what users and libraries use to access data. The Matrix structure encapsulates all information about the array, including the element that is used to initialize the map . The code sets the dimensions, selects and initializes the structure, then initializes the array, and then uses it as a user and as a library. Finally, the allocated memory is freed.

In practice, you probably want to break this down into several separate functions.

Source: 2da.c :

 #include <inttypes.h> #include <stdio.h> #include <stdlib.h> #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; } 

Output example

When running under valgrind 3.10.0 on Mac OS X 10.9.5 with GCC 4.9.1, I got the following result, The header "stderr.h" is in $HOME/inc and declares err_syserr() , and libjl.a is in $HOME/lib/64 and provides an implementation for err_syserr() , a function that reports this error message, and the error identified by errno and the outputs. I'm too lazy to write code in this program this time. (Searching user '[c]: 15168 err_syserr' in SO for search Protecting a shared memory segment with a semaphore does not work , which has essentially equivalent code. T call err_setarg0() in the code in this answer.)

 $ 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) $ 

The still reachable block is a buffer for stdout ; if I included fclose(stdout); before returning from main() , it will go. The Mac OS X runtime library also allocates a lot of memory, but this usage is identified in suppressed information.




Comment and Answer

I do all the initialization, as you see in two lines. But the problem is not initialization; the problem is that in each frame the values โ€‹โ€‹of the map change. Therefore, I only need a โ€œmapโ€ that points directly to a โ€œborder mapโ€. map[0][0] - boundaries_map[20][20] etc. I tried to declare a global **map and then write the second line to the main, but I get an error. (*map)[dim_x+40] This is **map , isn't it?

I'm not sure I fully understand what you need, which is one of the reasons this answer took a long time.

You cannot have global variables that are VLAs; they can only be distributed in functions, either on the stack, or as local variables, or on the heap via malloc() et al. The source code that I showed allows you to define an array through a global variable, a double pointer, which can be accessed from any code that a double pointer can read.

The code below can be seen as an exercise in building a VLA. It uses malloc() to create a VLA, recording where it was created by a pointer to a VLA. This can be passed to a function, similar to how a stack-based VLA is passed. The code compiles under GCC 4.9.1 on Mac OS X 10.9.5:

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

It works clean and leak free according to valgrind .

Source: 2dv.c :

 #include <stdio.h> #include <stdlib.h> 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'); } } 

Note the use of *vla and *vla_2 to pass *vla_2 to functions. Since vla and vla_2 are pointers to vla_2 , *vla is the VLA that functions expect.

Output:

  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 
0
Oct 14 '14 at 3:28
source share



All Articles