It might be a stupid question, but I wonder if there is a efficient way to do this.
The situation:
int* array = malloc(n * m * sizeof(int));
//want to convert array into M[n][m]
what I am doing now:
int** M = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++, array += m)
M[i] = array;
I don't think the conversion should be this complex. Is there any simple syntax C provided? Can I declare an extern M[n][m]
then set its address to the array?
(error handling and memory management in the sample is omitted for simplicity. Just think it as a part of some function.)
After:
int* array = malloc(n * m * sizeof(int));
you can do:
int (*M)[m] = (int(*)[m])array;
and then use M[1][2]
for example.
You could have done that in the first place too :
int (*M)[m] = malloc( n * sizeof *M );
You can't declare global arrays in C without giving them a specific numerical size. This is because global variables are static and the compiler can't allocate a variable amount of memory for a global array.
In C you've got to remember that an array is actually just a pointer. When you're asking for int *array = malloc(n * sizeof(int))
what you're telling the compiler is that you need n
lots of 4 byte blocks of int type reserved side by side in memory, where the value of array
is actually a pointer to the first 4 byte block.
When you are accessing elements of an array you are actually doing pointer arithmetic and dereferencing the pointer, but this is hidden in the array[i]
syntax. So, when array has int type, array[2]
translates as go to the location given by the array pointer (ie the head) now move 2 * 4 bytes along in memory and dereference the pointer to access the integer stored there.
So when you're creating a 2-d array as you've discussed, there really isn't a better way of doing it. Make sure you have a firm grip on what it actually is you're getting from the compiler. Pointers are (on 64-bit machines anyway) 8 bytes and ints are 4 bytes. So when you call int **M = malloc(sizeof(int*) * m
the compiler allocates you m blocks of width 8 bytes each, all of which have type int*.
From other programming languages it seems very over the top having to declare a pointer reference to a block of pointers, but getting passed the higher level idea of an array and considering them as a collection of pointers will really help you in the long run. When you need to pass these data types between functions you need to be able to have a firm idea of what you are actually manipulating; a pointer, a value, a pointer to a pointer? It will help you a lot in debugging code these ideas, as it is very easy to try and perform computations on pointers rather than values.
3 Useful Tips:
calloc(n, sizeof(int))
might be a better fit than calling malloc because calloc automatically initialises your entries to zero whereas malloc doesn't. The tricky part is declaring the variable to hold the pointer to the allocated array; the rest is straight-forward — assuming you have a C99 or later compiler.
#include <stdio.h>
#include <stdlib.h>
static void print_2dvla(int rows, int cols, int data[rows][cols])
{
for (int i = 0; i < rows; i++)
{
printf("%2d: ", i);
for (int j = 0; j < cols; j++)
printf(" %4d", data[i][j]);
putchar('\n');
}
}
int main(void)
{
int m = 10;
int n = 12;
int (*M)[m] = malloc(n * m * sizeof(M[0][0]));
if (M == NULL)
{
fprintf(stderr, "Failed to allocate %zu bytes memory\n", n * m * sizeof(M[0][0]));
exit(EXIT_FAILURE);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
M[i][j] = (i + 1) * 100 + (j + 1);
}
print_2dvla(n, m, M);
free(M);
return 0;
}
Example output:
0: 101 102 103 104 105 106 107 108 109 110
1: 201 202 203 204 205 206 207 208 209 210
2: 301 302 303 304 305 306 307 308 309 310
3: 401 402 403 404 405 406 407 408 409 410
4: 501 502 503 504 505 506 507 508 509 510
5: 601 602 603 604 605 606 607 608 609 610
6: 701 702 703 704 705 706 707 708 709 710
7: 801 802 803 804 805 806 807 808 809 810
8: 901 902 903 904 905 906 907 908 909 910
9: 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
10: 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
11: 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
The key line is:
int (*M)[m] = malloc(n * m * sizeof(M[0][0]));
This says that M
is a pointer to an array of int
arrays each of which has the dimension m
. The rest of the code simply uses that array with the usual 2-subscript notation — M[i][j]
etc. It can be passed to functions. I've not shown it here, but it is trivial to put the initialization code into a function too, and then have several different sizes of matrix in a single function.
Use an array of pointers.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n = 3, m = 4, i, j, count=0;
int *array[n];
for(i=0; i<n; i++)
array[i] = (int *)malloc(m * sizeof(int));
if( array[i] == NULL)
{
perror("Unable to allocate array");
exit(1);
}
// going to add number to your 2d array.
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
array[i][j] = ++count;
for (i=0; i < n; i++)
for (j=0; j < m; j++)
printf("%d ", array[i][j]);
// free memory
for(i=0; i<n; i++)
free(array[i]);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.