I've got stuck on compiling two-dimensional array in C using malloc();
Trying to compile my code in Microsoft Visual Studio Express 2013 I keep getting error 'a value of type "int **" cannot be assigned to an entity of type "int *"'
Here is my code:
int main() {
int lines = 0;
int **cord;
FILE *f = fopen("data.txt", "r");
if (f == NULL) return 0;
fscanf(f, "%d", &lines);
printf("%d", lines);
*cord = (int**)malloc(lines*sizeof(int*));
int i = 0;
for (i; i < lines; ++i)
{
cord[i] = (int*)malloc(2 * sizeof(int));
fscanf(f, "%d", cord[i][0]);
fscanf(f, "%d", cord[i][1]);
}
i = 0;
return 0;
}
Could anyone point me what is wrong there?
*cord = (int**)malloc(lines*sizeof(int*));
The variable cord
has type int **
, so the expression *cord
has type int *
. You're casting the result of malloc
to int **
. Thus, you're attempting to assign a value of type int **
to an expression of type int *
, which is an error. That line should be written as
cord = malloc( lines * sizeof *cord ); // note no cast, operand of sizeof
Style note - whitespace is your friend. Use it. Your eyes aren't going to be 20 years old forever.
If the number of columns is known at compile time (as it appears to be in this case), you can do a one-step allocation:
int (*cord)[2];
...
cord = malloc( lines * sizeof *cord );
if ( cord )
{
for ( int i = 0; i < lines; i++ )
{
fscanf( f, "%d", &cord[i][0] );
fscanf( f, "%d", &cord[i][1] );
}
...
free( cord );
}
else
// handle allocation failure
The variablecord
has type "pointer to 2-element array of int
", so the expression *cord
has type "2-element array of int
". sizeof *cord
gives us the number of bytes required for each subarray, so lines * sizeof *cord
gives us the total number of bytes required for the whole 2D array.
Advantages - single-step allocation (meaning single-step deallocation), and all the rows in the array are contiguous.
Disadvantages - May fail for very large arrays if memory is sufficiently fragmented, requires that you know the number of columns at compile time or that your compiler supports variable-length arrays (which were introduced in C99 and are optional as of C2011).
In general, your malloc
statements should be written as
T *ptr = malloc( N * sizeof *ptr ); // calloc( N, sizeof *ptr )
or
T *ptr = NULL;
...
ptr = malloc( N * sizeof *ptr ); // calloc( N, sizeof *ptr );
C doesn't require you to cast the result of malloc/calloc
1. C++ does require it since it doesn't allow implicit conversion of void
pointers, but if you're writing C++ you should be using new
and delete
instead of malloc
and free
.
malloc
and calloc
returned char *
instead of void *
, so for pre-C89 compilers the cast was required. MSVC supports the C89 standard, so you don't need the cast