Fabian Wauthier wrote:
Hi list,
I am trying to dynamically grow a 2 dimensional array (Atom ***Screen) of
pointers to a struct Atom (i.e. the head of a linked list). I am not
sure if this is the right way to do it:
/* Allocate 1st dimension */
if((Screen = (Atom ***) malloc(sizeof(Atom **) * Width)) == NULL)
perrexit("malloc");
/* Allocate 2nd dimension */
for(i = 0; i < Width; i++)
if((Screen[i] = (Atom **) malloc(sizeof(Atom *) * Height)) == NULL)
perrexit("malloc");
/* Set Screen all NULL initially */
for(i = 0; i < Width; i++)
for(j = 0; j < Height; j++)
Screen[i][j] = NULL; /* Can I do this? */
Can I then access Screen using normal Array subscript notation?
I keep getting strange behaviour in another part of the program, and
I'm not sure if this is the problem.
The faq offers various methods of creating the 2d array at:
http://www.eskimo.com/~scs/C-faq/q6.16.html
The allocations and assignments look ok here for an initial
allocation. Perhaps the source of the strange behavior is
somewhere else. Dynamic growing, reallocating, deallocating this 2d
array of pointers to linked lists can be tricky.
Function ReallocScreen below and the datatype Screen is one
way you may approach this code.
#include <stdio.h>
#include <stdlib.h>
typedef struct Atom
{
unsigned value;
struct Atom *next;
} Atom;
typedef struct Screen
{
Atom ***screen;
unsigned Width;
unsigned Height;
} Screen;
/* Prototypes */
int AddLINK( Screen *p,unsigned Welement, unsigned Helement,
unsigned value);
void PrintLINK(Screen *p, unsigned Welement, unsigned Helement);
void FreeLINK(Atom **p);
void FreeScreen(Screen *p);
int ReallocScreen(Screen *p, unsigned Width, unsigned Height);
int main(void)
{
Screen my = {NULL};
if(ReallocScreen(&my, 5,6)) /* 5x6 array of Atom pointers */
{
puts("Allocated an [5][6] array of pointers");
AddLINK(&my, 0, 0, 52);
AddLINK(&my, 0, 0,100);
AddLINK(&my,1, 0,200);
AddLINK(&my, 1, 0,300);
PrintLINK(&my,0,0);
PrintLINK(&my,1,0);
}
if(ReallocScreen(&my,1,1))
{
puts("\nReallocated the array[1][1] to check "
"if values changed\n");
PrintLINK(&my,0,0);
PrintLINK(&my,1,0);
puts("Element [1][0] and linked list has been deallocated");
}
FreeScreen(&my);
return 0;
}
int AddLINK( Screen *p,unsigned Welement, unsigned Helement,
unsigned value)
{
Atom *tmp;
if(Welement > p->Width || Helement > p->Height ||
(tmp = malloc(sizeof *tmp)) == NULL) return 0;
tmp->value = value;
tmp->next = p->screen[Welement][Helement];
p->screen[Welement][Helement] = tmp;
return 1;
}
void PrintLINK(Screen *p, unsigned Welement, unsigned Helement)
{
Atom *tmp;
if(Welement < p->Width && Helement < p->Height)
{
tmp = p->screen[Welement][Helement];
printf("Screen[%u][%u]: ",Welement,Helement);
for( ; tmp; tmp = tmp->next)
printf("%u -> ",tmp->value);
puts("NULL(End of Linked List)");
}
return;
}
void FreeLINK(Atom **p)
{
Atom *tmp;
for( ; *p; *p = tmp)
{
tmp = (*p)->next;
free(*p);
}
return;
}
void FreeScreen(Screen *p)
{
unsigned i,j;
for(i = 0;i < p->Width; i++)
for(j = 0; j < p->Height; j++)
FreeLINK(&p->screen[i][j]);
if(p->screen)
{
free(p->screen[0]);
free(p->screen);
}
p->screen = NULL;
p->Height = p->Width = 0;
return;
}
int ReallocScreen(Screen *p, unsigned Width, unsigned Height)
{
unsigned i,j;
Atom ***tmp;
tmp = malloc(Width * (sizeof *tmp));
if(!tmp) return 0;
tmp[0] = malloc(Width * Height * (sizeof **tmp));
if(!tmp[0])
{
free(tmp);
return 0;
}
for(i = 1; i < Width; i++)
tmp[i] = tmp[0] + i * Height;
for(i = 0; i < Width; i++)
for(j = 0; j < Height;j++)
{
if(i < p->Width && j < p->Height)
tmp[i][j] = p->screen[i][j];
else
tmp[i][j] = NULL;
}
for( ; i < p->Width;i++)
for(j = 0 ; j < p->Height; j++)
FreeLINK(&p->screen[i][j]);
if(p->screen)
{
free(p->screen[0]);
free(p->screen);
}
p->screen = tmp;
p->Width = Width;
p->Height = Height;
return 1;
}
--
Al Bowers
Tampa, Fl USA
mailto:
xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/