> Would data[2] be out of bounds? if so, this is not what I want.
Yes it would, and I've no idea now what you want.
Code:
#include <stdio.h>
#include <stdlib.h>
#define ASIZE 10
void foo ( ) {
// cdecl> explain int (*data)[2];
// declare data as pointer to array 2 of int
int (*data)[2];
data = malloc( sizeof(*data) * ASIZE );
// the minor dimension is fixed at 2, but you
// can have as many of the major dimension as
// you malloc.
for ( int i = 0 ; i < ASIZE ; i++ ) {
data[i][0] = 0;
data[i][1] = 1;
}
free(data);
}
void bar ( ) {
// cdecl> explain int *data[2];
// declare data as array 2 of pointer to int
int *data[2];
data[0] = malloc( sizeof(*data[0]) * ASIZE );
data[1] = malloc( sizeof(*data[1]) * ASIZE );
// the major dimension is fixed at 2, but you
// can have as many of the minor dimension as
// you malloc.
for ( int i = 0 ; i < ASIZE ; i++ ) {
data[0][i] = 0;
data[1][i] = 1;
}
free(data[0]);
free(data[1]);
}
int main ( ) {
foo();
bar();
return 0;
}
$ gcc -std=c99 -Wall -Wextra -g foo.c
$ valgrind ./a.out
==3976== Memcheck, a memory error detector
==3976== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3976== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==3976== Command: ./a.out
==3976==
==3976==
==3976== HEAP SUMMARY:
==3976== in use at exit: 0 bytes in 0 blocks
==3976== total heap usage: 3 allocs, 3 frees, 160 bytes allocated
==3976==
==3976== All heap blocks were freed -- no leaks are possible
==3976==
==3976== For counts of detected and suppressed errors, rerun with: -v
==3976== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
> Would you mind providing some situations where casting is a bad idea here?
Yes, in older versions of C, omitting the inclusion of stdlib.h would leave malloc without a prototype - at which point the compiler would automatically assume malloc returned an int. On machines where pointers have different size to int (or machines which use different registers for different types), the code is invisibly broken because the cast hides the error.
int *test[5];
test = malloc(sizeof(test[5])*10);
free(test);
and here is the compilation log:
$ gcc -o test test.c
test.c: In function ‘main’:
test.c:7: error: incompatible types when assigning to type ‘int *[5]’ from type ‘void *’
The error is because you can't assign an array in C.
test[0] = malloc.... is valid
test = malloc is NOT valid
You can't synthesise int test[5][10] from int *test[5] with a single call to malloc.
int (*test)[10] = malloc(5 * sizeof(*test) ); synthesises int test[5][10], but it only works if the minor dimension is a compile time constant.