I compile some code with visual studio 9.0 (2008).
The behave as expected, but when I allocate some 2D array with some hand made functions, Visual-Studio generates some C4133 warning:
void ** alloc_2d(int w, int h, size_t type_size);
void free_d2(void ** mem);
int main (void)
{
float ** data;
/* Here is generated a C4133 warning:
"incompatible type from void ** to float **" */
data = alloc_2d(100, 100, sizeof **data);
/* do things with data */
/* free data */
free_2d(data);
return 0;
}
I understand why this warning is generated, but I wonder what I should do to make it quiet.
What should I do?
alloc_2d calls (with some macros specific to
visual studio)?Second question:
Behind the void** are hidden two arrays: one big to store all data I need to be contiguous, and one other to browse through differents lines.
The implementation looks like (I removed the error checking)
void **alloc_2D_array(int w, int h, size_t size)
{
void ** mem = malloc(w * sizeof *mem);
*mem = malloc(w*h*size);
for (i = 1; i < w; ++i)
{
mem[i] = (void*)((char*)mem[0] + i*w*size);
}
return mem;
}
From the signature, I assume your function is implemented roughly like this (plus error checking I'm leaving out here for brevity):
void **alloc_2d(int w, int h, size_t type_size)
{
void **pointers = malloc(h * sizeof *pointers);
for (size_t i = 0; i < h; ++i)
{
pointers[i] = malloc(w * type_size);
}
return pointers;
}
Some remarks on this:
w * h * type_size.void ** returned from it to float **. This is because there's no guarantee that pointers to different types have the same representation -- they could even have different sizes. See also Are there any platforms where pointers to different types have different sizes?. By casting void ** to float **, you're treating an array of void * as if it was and array of float *. Although probably fine on your typical modern PC platform, this can go completely wrong.That said, you could avoid the cast by simply having your function return void * instead of void **, but this would only hide the problem: void * is the generic pointer type and the compiler will allow implicit conversion to any other pointer type, but you'd still access your void * array using the wrong pointer type that way.
I suggest allocating a flat array instead and calculate the offsets manually, like this:
size_t rows = 100;
size_t cols = 100;
float *data = malloc(cols * rows * sizeof *data);
data[cols*5 + 3] = 1.41;
// ...
free(data);
As an alternative, you can use variable-length arrays (obligatory in C99, optional but almost always supported in C11 -- maybe not supported by Microsoft ....) to dynamically allocate a real 2d array:
size_t rows = 100;
size_t cols = 100;
float (*data)[cols] = malloc(rows * sizeof *data);
data[5][3] = 1.41;
// ...
free(data);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With