YamSeng
asked on
3D array. How to malloc
I have an array which is 3d. I used to initialise it by just
GLubyte array[256][512][3];
It's for storing pixel colors in gtk. If I want to malloc the size because it may be variable, how can I do it?
I tried this, but it didn't work.
GLubyte *** array;
array = malloc(sizeof(GLubyte) * 256);
for(i = 0; i < 256; i++)
{
array[i] = malloc(sizeof(GLubyte) * 512)
for(j = 0; j < 512; j++)
{
array[i][j] = malloc(sizeof(GLubyte) * 3);
}
}
somehow when I tried accessing it, halfway, it'll have segmentation fault or something.
But if I initialise it with
GLubyte array[256][512][3];
no problems.
Any ideas?
Yam
GLubyte array[256][512][3];
It's for storing pixel colors in gtk. If I want to malloc the size because it may be variable, how can I do it?
I tried this, but it didn't work.
GLubyte *** array;
array = malloc(sizeof(GLubyte) * 256);
for(i = 0; i < 256; i++)
{
array[i] = malloc(sizeof(GLubyte) * 512)
for(j = 0; j < 512; j++)
{
array[i][j] = malloc(sizeof(GLubyte) * 3);
}
}
somehow when I tried accessing it, halfway, it'll have segmentation fault or something.
But if I initialise it with
GLubyte array[256][512][3];
no problems.
Any ideas?
Yam
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
try the following:
GLubyte *** array;
array = malloc(sizeof(* * GLubyte) * 256);
for(i = 0; i < 256; i++)
{
array[i] = malloc(sizeof(* GLubyte) * 512)
for(j = 0; j < 512; j++)
{
array[i][j] = malloc(sizeof(GLubyte) * 3);
}
}
Take care of the stars in the first two mallocs!!
regards
GLubyte *** array;
array = malloc(sizeof(* * GLubyte) * 256);
for(i = 0; i < 256; i++)
{
array[i] = malloc(sizeof(* GLubyte) * 512)
for(j = 0; j < 512; j++)
{
array[i][j] = malloc(sizeof(GLubyte) * 3);
}
}
Take care of the stars in the first two mallocs!!
regards
or use calloc()
GLubyte *** array;
array = calloc(256, sizeof(GLubyte));
for(i = 0; i < 256; i++)
{
array[i] = calloc(512, sizeof(GLubyte))
for(j = 0; j < 512; j++)
{
array[i][j] = calloc(3, sizeof(GLubyte));
}
}
GLubyte *** array;
array = calloc(256, sizeof(GLubyte));
for(i = 0; i < 256; i++)
{
array[i] = calloc(512, sizeof(GLubyte))
for(j = 0; j < 512; j++)
{
array[i][j] = calloc(3, sizeof(GLubyte));
}
}
GLubyte *** array;
array = (GLubyte***)calloc(256, sizeof(GLubyte));
for(i = 0; i < 256; i++)
{
array[i] = (GLubyte**)calloc(512, sizeof(GLubyte))
for(j = 0; j < 512; j++)
{
array[i][j] = (GLubyte*)calloc(3, sizeof(GLubyte));
}
}
array = (GLubyte***)calloc(256, sizeof(GLubyte));
for(i = 0; i < 256; i++)
{
array[i] = (GLubyte**)calloc(512, sizeof(GLubyte))
for(j = 0; j < 512; j++)
{
array[i][j] = (GLubyte*)calloc(3, sizeof(GLubyte));
}
}
Glubyte (*array)[256][512][3];
*array = malloc(sizeof(*array));
for (i = 0; i < 256; ++i)
for (j = 0; j < 512; ++j) {
(*array)[i][j][0] = x;
(*array)[i][j][1] = y;
(*array)[i][j][2] = z;
}
ie. declare array to be a pointer to a 256*512*3 array of chars.
*array = malloc(sizeof(*array));
for (i = 0; i < 256; ++i)
for (j = 0; j < 512; ++j) {
(*array)[i][j][0] = x;
(*array)[i][j][1] = y;
(*array)[i][j][2] = z;
}
ie. declare array to be a pointer to a 256*512*3 array of chars.
Suppose int array[256][512][3];
array=(int ***)malloc(256 * sizeof(int **));
for(i=0;i<256;i++)
{
array[i]=(int **)malloc(512 * sizeof(int*));
for(j=0;j<512;j++)
{
array[i][j]=(int *)malloc(3 * sizeof(int));
}
}
c=(double **)malloc(n * sizeof(double *));
for(i=0;i<n;i++)
c[i]=(double *)malloc(n * sizeof(double));
I think it will work perfectly.
Try this,
GLubyte ***array;
array =(GLubyte***) malloc(sizeof(GLubyte **) * 256);
for(i = 0; i < 256; i++)
{
array[i] = (GLubyte**)malloc(sizeof(G Lubyte *) * 512)
for(j = 0; j < 512; j++)
{
array[i][j] = (GLubyte*) malloc(sizeof(GLubyte) * 3);
}
}
GLubyte ***array;
array =(GLubyte***) malloc(sizeof(GLubyte **) * 256);
for(i = 0; i < 256; i++)
{
array[i] = (GLubyte**)malloc(sizeof(G
for(j = 0; j < 512; j++)
{
array[i][j] = (GLubyte*) malloc(sizeof(GLubyte) * 3);
}
}
kotan,
I have written the same thing what you have wirtten
tapas
I have written the same thing what you have wirtten
tapas
oh! Sorry!
The points should be yours. :-)
The points should be yours. :-)
For my comment;
stars that i state should be after the GLubyte.
sorry for that
stars that i state should be after the GLubyte.
sorry for that
ASKER
wow...give me a sec to check it out. It's just 1 day and there's so much response!
Thanks
Thanks
ASKER
right....I've some results.
I realise that having an array[x][y][z] is different to having an ***array and malloc-ing it.
Maybe the structure of the array is different.
What exactly happened was that if I have 2 arrays
int array[x][y][x];
and
int ***array2; which later uses malloc accordingly.
But the interesting part is that
array[1][1][1] and array2[1][1][1] can have the same value. But if a function were to use the arrays created sequentially, I think the intialised array will not work. Only the malloc-ed array will work.
In the function I use (infact it's some OpenGl library; gtkgl), that function don't access the array sequentially.
So, my question is...is there a way to malloc it, or dynamically define the array such that it is exacly the same as a initialised normal array?
I realise that having an array[x][y][z] is different to having an ***array and malloc-ing it.
Maybe the structure of the array is different.
What exactly happened was that if I have 2 arrays
int array[x][y][x];
and
int ***array2; which later uses malloc accordingly.
But the interesting part is that
array[1][1][1] and array2[1][1][1] can have the same value. But if a function were to use the arrays created sequentially, I think the intialised array will not work. Only the malloc-ed array will work.
In the function I use (infact it's some OpenGl library; gtkgl), that function don't access the array sequentially.
So, my question is...is there a way to malloc it, or dynamically define the array such that it is exacly the same as a initialised normal array?
Tapas, you were very close. The problem with the mallocs here is that only the last pointer is pointing to an actual "GLubyte". The first 2 pointers are simply pointing to another pointer of size int (actually unsigned, but is the same size). So the malloc should look like the following.
GLubyte *** array;
array=(GLubyte ***)malloc(256 * sizeof(int));
for(i=0;i<256;i++)
{
array[i]=(GLubyte **)malloc(512 * sizeof(int));
for(j=0;j<512;j++)
{
array[i][j]=(GLubyte *)malloc(3 * sizeof(GLubyte));
}
}
GLubyte *** array;
array=(GLubyte ***)malloc(256 * sizeof(int));
for(i=0;i<256;i++)
{
array[i]=(GLubyte **)malloc(512 * sizeof(int));
for(j=0;j<512;j++)
{
array[i][j]=(GLubyte *)malloc(3 * sizeof(GLubyte));
}
}
YamSeng, see my comment above. I take it you do not want an array of pointers, just a 393216 GLubyte size block of memory treated as a 3-dim array. If so, use the syntatic sugar I mentioned previously which is neccessary because in 'C' [] has higher precedence than pointer dereference.
Black :: I think u are wrong.
Bcos u have to pointing other address.
so u have to assign like as:
array=(int ***)malloc(256 * sizeof(int **));
YAMSENG:: U just apply my comment, i think it will work that u want.
array=(int ***)malloc(256 * sizeof(int **));
for(i=0;i<256;i++)
{
array[i]=(int **)malloc(512 * sizeof(int*));
for(j=0;j<512;j++)
{
array[i][j]=(int *)malloc(3 * sizeof(int));
}
}
Bcos u have to pointing other address.
so u have to assign like as:
array=(int ***)malloc(256 * sizeof(int **));
YAMSENG:: U just apply my comment, i think it will work that u want.
array=(int ***)malloc(256 * sizeof(int **));
for(i=0;i<256;i++)
{
array[i]=(int **)malloc(512 * sizeof(int*));
for(j=0;j<512;j++)
{
array[i][j]=(int *)malloc(3 * sizeof(int));
}
}
Tapas,
I am very right. Tell me, what is the size of an "int **" ? Is it not simply a pointer? That pointer will consume 32 bits (assuming a 32 bit machine). Therefor:
sizeof(int **********) = sizeof(int *) = sizeof(int) = 32 bits (4 bytes) any way you slice it!
Try printing it out. See what you get. (grumble)
Also, the last allocation "array[i][j]=(int *)malloc(3 * sizeof(int));" that you are trying to show is incorrect. He is looking for an array of GLubytes, not an array of integers. Please show some proof that I am wrong, because I have done this type of allocation thousands of times, and am confident in my answer.
I am very right. Tell me, what is the size of an "int **" ? Is it not simply a pointer? That pointer will consume 32 bits (assuming a 32 bit machine). Therefor:
sizeof(int **********) = sizeof(int *) = sizeof(int) = 32 bits (4 bytes) any way you slice it!
Try printing it out. See what you get. (grumble)
Also, the last allocation "array[i][j]=(int *)malloc(3 * sizeof(int));" that you are trying to show is incorrect. He is looking for an array of GLubytes, not an array of integers. Please show some proof that I am wrong, because I have done this type of allocation thousands of times, and am confident in my answer.
ASKER
tapas, I've tried your code as well as all other codes as well.....none of them worked.
ecw, yours had compilation problem. I'll post the errors later when I get back home.
ecw, yours had compilation problem. I'll post the errors later when I get back home.
ASKER
BlackDiamond,
I'll try your codes tonight. Till then, thanks.
I'll try your codes tonight. Till then, thanks.
YAMSENG::
I have tried this code in VC++. It works fine. but u did not get any result? how it is possible?
int array[256][512][3];
array=(int ***)malloc(256 * sizeof(int **));
for(i=0;i<256;i++)
{
array[i]=(int **)malloc(512 * sizeof(int*));
for(j=0;j<512;j++)
{
array[i][j]=(int *)malloc(3 * sizeof(int));
}
}
ASKER
Visual C? Oh...Then I'm not sure....Coz I'm actually using doing opengl using gtkgl. And it's on a Linux platform...
or maybe it works for int but not GLubytes? 8) I have no idea.....
Yam
or maybe it works for int but not GLubytes? 8) I have no idea.....
Yam
of course it did, it should've been
array = malloc(sizeof(*array));
array = malloc(sizeof(*array));
ASKER
BlackDiamond, your code didn't work as well....
ecw, your malloc code works BUT it doesn't allow me to make the size of the array variable. So I can't use it either.
I think what happens is that, the structure of a 3D array and a malloc-ed 3D array doesn't seems to be the same structually. I strongly believe this could be the reason why it's failing me when I pass it to a function in gtlgl.
I'll post more info when I've finished testing the differences in the structure of the arrays.
ecw, your malloc code works BUT it doesn't allow me to make the size of the array variable. So I can't use it either.
I think what happens is that, the structure of a 3D array and a malloc-ed 3D array doesn't seems to be the same structually. I strongly believe this could be the reason why it's failing me when I pass it to a function in gtlgl.
I'll post more info when I've finished testing the differences in the structure of the arrays.
Some remarks.
If you define arrays "int array[10][15]", then a memory block of 150 consecutive 'int's is allocated. (in total -if 32 bit machine- you have 600 bytes)
If you define int ** array and do mallocs to 'simulate the [10][15] structure', it means you have a double reference to the 'values'. Array is a pointer (4bytes) pointing to an array of 10 pointers (40 bytes). Eahc of these 10 pointers point to an array of 15 int's. These last 15 arrays are not necessary 'consecutive' place in memory. It's likely that are some gaps. In total teh **array solution takes 644 bytes in memory. Thus abviously not the same 'layout' as array[10][15].
To make it more clear to print out all value of array[10][15], one can use the following
int *i;
int array[10][15];
// initialize array
i=&array[0][0];
for(j=0;j<512;j++)
print ("%d:%d\n",j,i[j]);
Please always bare in mind that although you can do 'about' the same with arrays as with pointers, they behave different, and have 'internally in memory' different layouts.
If you define arrays "int array[10][15]", then a memory block of 150 consecutive 'int's is allocated. (in total -if 32 bit machine- you have 600 bytes)
If you define int ** array and do mallocs to 'simulate the [10][15] structure', it means you have a double reference to the 'values'. Array is a pointer (4bytes) pointing to an array of 10 pointers (40 bytes). Eahc of these 10 pointers point to an array of 15 int's. These last 15 arrays are not necessary 'consecutive' place in memory. It's likely that are some gaps. In total teh **array solution takes 644 bytes in memory. Thus abviously not the same 'layout' as array[10][15].
To make it more clear to print out all value of array[10][15], one can use the following
int *i;
int array[10][15];
// initialize array
i=&array[0][0];
for(j=0;j<512;j++)
print ("%d:%d\n",j,i[j]);
Please always bare in mind that although you can do 'about' the same with arrays as with pointers, they behave different, and have 'internally in memory' different layouts.
ASKER
Hmm....that's what I've just found out now. 8) Maybe it's because of the pointers...and there's gaps when I printed them out sequentially.
So, I'm thinking maybe I have to malloc the total size of it, at once....and use them sequential....but I'll have to verify them later....
So, I'm thinking maybe I have to malloc the total size of it, at once....and use them sequential....but I'll have to verify them later....
calculate the total, and have the 3d array simulated by 3 for loops.
This way you have the dynamic solution, AND the consecutive 'memory' layout.
This way you have the dynamic solution, AND the consecutive 'memory' layout.
No you made no mention of dynamically sizing the the array dimensions, if that's what you want, you have to use the method elfie described. The structure of a 3D array and a malloced 3D array are identical, just one contiguous block of memory. The difference is in how you access it. I've seen too many people assume that arrays and pointers are interchangable, and use code similar to,
(in file 1)
int data[100];
(and in file 2)
extern int *data;
And then wonder why the code crashes
(in file 1)
int data[100];
(and in file 2)
extern int *data;
And then wonder why the code crashes
ASKER
Malloc-ing a 3D array using "for loops" and using pointer to pointers to pointers will have gaps between these mallocs. So it's never contiguous. I've done a simple 3D array using malloc for each x,y,z and have realised that they are not contiguous.
ecw, I did mention in my question, that the size needs to be variable.
Someone mentioned about using a 1D array and proper offset. Now I think this could be the only way so as to make it compatible. But when I was trying his code, I think the offsets were slightly off or something like that. Nonetheless, I'll give it a shot again tonight.
Later.
ecw, I did mention in my question, that the size needs to be variable.
Someone mentioned about using a 1D array and proper offset. Now I think this could be the only way so as to make it compatible. But when I was trying his code, I think the offsets were slightly off or something like that. Nonetheless, I'll give it a shot again tonight.
Later.
what i ment with malloc the 3 for loops is as follows (only 1 malloc, and use calculations to simulate the 3d)
something like
int max_i, max_j, max_k;
char *array;
char *c;
array = malloc (max_i*max_j*max_k);
for(i=0;i<max_i;i++)
for(j=0;j<max_j;j++)
for(k=0;j<max_j;k++)
for(i=0;i<max_i;i++)
array [i*max_k*max_j+j*max_x+k] = init_value;
With this method you can access the array like a 3D array.
If you want make a define of it
#define get_array_el(i,j,k) array[i*max_k*max_j+j*max_ x+k]
thsi way the code can look like
for(i=0;i<max_i;i++)
for(j=0;j<max_j;j++)
for(k=0;j<max_j;k++)
get_array_el(i,j,k) = init_value;
Defined like this the array can be scanned by 1 loop as can be done for 'real'array.
c=&array[0];
and use c as a pointer to elements. To reach the next element use c++.
something like
int max_i, max_j, max_k;
char *array;
char *c;
array = malloc (max_i*max_j*max_k);
for(i=0;i<max_i;i++)
for(j=0;j<max_j;j++)
for(k=0;j<max_j;k++)
for(i=0;i<max_i;i++)
array [i*max_k*max_j+j*max_x+k] = init_value;
With this method you can access the array like a 3D array.
If you want make a define of it
#define get_array_el(i,j,k) array[i*max_k*max_j+j*max_
thsi way the code can look like
for(i=0;i<max_i;i++)
for(j=0;j<max_j;j++)
for(k=0;j<max_j;k++)
get_array_el(i,j,k) = init_value;
Defined like this the array can be scanned by 1 loop as can be done for 'real'array.
c=&array[0];
and use c as a pointer to elements. To reach the next element use c++.
ASKER
you were the first to suggest using a 1D array. But the offset you gave me were wrong.
anyway, I'm using array[counter++] and it's easier.
anyway, I'm using array[counter++] and it's easier.
Marc
#include <stdio.h>
void func(int i, int j, int k);
int main(void)
{
func(3,4,5);
/*
In this example, there are 3*4*5 = 60 values (0-59)
*/
return 0;
}
void func(int i, int j, int k)
{
int array[i][j][k];
int a, b, c;
int d = 0;
for ( a = 0; a < i; a++ )
for ( b = 0; b < j; b++ )
for ( c = 0; c < k; c++ )
array[a][b][c] = d++;
for ( a = 0; a < i; a++ ) {
for ( b = 0; b < j; b++ ) {
for ( c = 0; c < k; c++ )
printf("%02i ", array[a][b][c]);
printf(" \n");
}
printf("\n");
}
}