473,385 Members | 1,356 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Dynamically growing an array (pointer question)


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.

I hope this wasn't to verbose.

Thanks for any pointers.

Fabian
Nov 14 '05 #1
7 3084
Fabian Wauthier <fl*@removeme.copyleft.de> wrote:
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.


I guess you know that you don't have a real 2-dimensional array here,
you're "faking" one by having an array of pointers, each pointing to
an array of Atom structure pointers and use that with the declaration

SOME_TPYE **a;

the expression "a[i][j]" is evaluated as "*(*(a+i)+j)" to be able to
empoy the normal array subscript notation for something that isn't a
2-dimensional C array. So you won't, for example, be able to use the
sizeof operator on that "array" and get the same results as with a
real array. And you won't be able to use functions written for use
with a real 2-dimensional C array of Atom pointers (they'd expect an
Atom** and not an Atom***). But as long as you keep that in mind your
use of 'Screen' with the notation for 2-dimensional arrays looks ok.

BTW, you can save a lot of calls of malloc() (and later of free()) if
you allocate the whole set of Atom pointers a once like this:

if ( ( *Screen = malloc( Width * Height * sizeof **Screen ) ) == NULL )
perrexit( "malloc" );

for ( i = 1; i < Width; i++ )
Screen[ i ] = Screen [ i - 1 ] + Height;

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #2
On 12 Apr 2004 11:08:33 GMT, Je***********@physik.fu-berlin.de wrote:

BTW, you can save a lot of calls of malloc() (and later of free()) if
you allocate the whole set of Atom pointers a once like this:

if ( ( *Screen = malloc( Width * Height * sizeof **Screen ) ) == NULL )
perrexit( "malloc" );
If the OP has defined Screen as he indicated, via:
Atom ***Screen;
then, at the very least, I do not think you want that asterisk in front of
'Screen' up there.

After your single malloc, you've got a pointer (Screen) to a 2D matrix of
atom pointers; you no longer have the situation where Screen points to the
first element of an "array of arrays of atom pointers" as in the OP's
scenario, so whatever you're doing down below, I don't see how it can be
healthy:
for ( i = 1; i < Width; i++ )
Screen[ i ] = Screen [ i - 1 ] + Height;

Regards, Jens


Since the OP mentioned he wants to "dynamically grow" the array, rather
than just dynamically /allocating/ it, he'd need the array of pointer to
arrays in order to, say, grow the Height but not the Width. I have no
idea if that's what he really wants to do or not, but it's another thing
that would be difficult with the "one malloc fits all" approach rather
than allocating the columns piecemeal as he did.
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: Download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Nov 14 '05 #3
Leor Zolman <le**@bdsoft.com> wrote:
On 12 Apr 2004 11:08:33 GMT, Je***********@physik.fu-berlin.de wrote:
BTW, you can save a lot of calls of malloc() (and later of free()) if
you allocate the whole set of Atom pointers a once like this:

if ( ( *Screen = malloc( Width * Height * sizeof **Screen ) ) == NULL )
perrexit( "malloc" );
If the OP has defined Screen as he indicated, via:
Atom ***Screen;
then, at the very least, I do not think you want that asterisk in front of
'Screen' up there. After your single malloc, you've got a pointer (Screen) to a 2D matrix of
atom pointers; you no longer have the situation where Screen points to the
first element of an "array of arrays of atom pointers" as in the OP's
scenario, so whatever you're doing down below, I don't see how it can be
healthy:

for ( i = 1; i < Width; i++ )
Screen[ i ] = Screen [ i - 1 ] + Height;

Sorry, I meant the OP to keep the first allocation of the array of
pointers to Atom pointers:

if ( ( Screen = malloc( Width * sizeof *Screen ) ) == NULL )
perrexit( "malloc" );

and only then to allocate memory for the arrays of Atom pointers all at
once, initializing Screen[0] (aka *Screen) with that pointer and finally
setting up the rest of the pointers, making them point into that memory
region.
Since the OP mentioned he wants to "dynamically grow" the array, rather
than just dynamically /allocating/ it, he'd need the array of pointer to
arrays in order to, say, grow the Height but not the Width. I have no
idea if that's what he really wants to do or not, but it's another thing
that would be difficult with the "one malloc fits all" approach rather
than allocating the columns piecemeal as he did.


That's correct, of course. I made the mistake of interpreting "dynami-
cally grow" to mean allocate dynamically (as opposed to creating a true
2-dimensional array with fixed sizes). If the OP really wants to be able
to change the sizes dynamically afterwards there's obviously no way
around allocating each array of pointers to Atom pointers of size
'Height' individually. Sorry for the confusion and thanks for pointing
that out.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #4


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/

Nov 14 '05 #5
On 11 Apr 2004 20:51:36 +0100, Fabian Wauthier
<fl*@REMOVEME.copyleft.de> 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)
Lose the cast. The only thing it does is prevent the compiler for
telling you that you forgot to include stdlib.h. You would like to
know if that is the case since your code would invoke undefined
behavior in C89.

If for some reason you ever decide to change the type of Atom, you
would have to update all the sizeof operands. For this reason, most
in this group recommend
if ((Screen = malloc(Width * sizeof *Screen)) = NULL)
perrexit("malloc");

/* Allocate 2nd dimension */

for(i = 0; i < Width; i++)
if((Screen[i] = (Atom **) malloc(sizeof(Atom *) * Height)) == NULL)
perrexit("malloc");
Here it would be
if ((Screen[i] = malloc(Height * sizeof *Screen[i])) == NULL)

/* 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? */
Yes. Screen[i][j] is a pointer.

Can I then access Screen using normal Array subscript notation?
Yes, as long as you remember that Screen[i][j] is a pointer and not a
struct.

I keep getting strange behaviour in another part of the program, and
I'm not sure if this is the problem.


Without the code, it is like playing roulette. I bet the problem is
on line 42.
<<Remove the del for email>>
Nov 14 '05 #6
Barry Schwarz <sc******@deloz.net> writes:
On 11 Apr 2004 20:51:36 +0100, Fabian Wauthier
<fl*@REMOVEME.copyleft.de> 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)
Lose the cast. The only thing it does is prevent the compiler for
telling you that you forgot to include stdlib.h. You would like to
know if that is the case since your code would invoke undefined
behavior in C89.

If for some reason you ever decide to change the type of Atom, you
would have to update all the sizeof operands. For this reason, most
in this group recommend
if ((Screen = malloc(Width * sizeof *Screen)) = NULL)
perrexit("malloc");

/* Allocate 2nd dimension */

for(i = 0; i < Width; i++)
if((Screen[i] = (Atom **) malloc(sizeof(Atom *) * Height)) == NULL)
perrexit("malloc");


Here it would be
if ((Screen[i] = malloc(Height * sizeof *Screen[i])) == NULL)

/* 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? */


Yes. Screen[i][j] is a pointer.

Can I then access Screen using normal Array subscript notation?


Yes, as long as you remember that Screen[i][j] is a pointer and not a
struct.


Yes, I use this screen to hold a new ordering of Atoms (which I
allocated in a seperate step). On each run, the Screen array is
cleared and the atoms newly ordered into the Screen array as linked
lists.

I keep getting strange behaviour in another part of the program, and
I'm not sure if this is the problem.
Without the code, it is like playing roulette. I bet the problem is
on line 42.


Hi Barry and all,

Thanks everyone for your help, and pointers. I think I'll comment much
more code, and see what's left then.

Cheers,
Fabian


<<Remove the del for email>>

Nov 14 '05 #7
Barry Schwarz <sc******@deloz.net> writes:
On 11 Apr 2004 20:51:36 +0100, Fabian Wauthier
<fl*@REMOVEME.copyleft.de> wrote:

[...]

Yes. Screen[i][j] is a pointer.

Can I then access Screen using normal Array subscript notation?
Yes, as long as you remember that Screen[i][j] is a pointer and not a
struct.


I actually used the Screen array only to hold an ordering of Atoms
(which I allocated and hold in a seperate array). I basically want to
check whether two Atoms share same x/y values (cast to int). Using the
Screen with x/y as indexes should work much faster than using two
nested for-loops.

There is in fact no real need for a totally dynamic 2d array (as I
probably implied). I just want to build one on startup.

So I guess Jens' solution could do the trick.


I keep getting strange behaviour in another part of the program, and
I'm not sure if this is the problem.


Without the code, it is like playing roulette. I bet the problem is
on line 42.


Thanks for all your help and pointers. I'll make the changes you
suggested comment much more code and see what happens.

Cheers, Fabian
Nov 14 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Chris Haynes | last post by:
Hello all, I have a structure: typedef struct UVstruct { float u, v; } uv; Inside a function (A) i declare a pointer to an instance of this structure:
7
by: masood.iqbal | last post by:
I am having lots of trouble getting a simple program that initializs a dynamically allocated 2D array to work. My 2D array is not getting initialized properly, and additionally I am getting a...
2
by: songfire | last post by:
Hi everybody! Just wondering if it is possible to point to variables in the heap. For example, is this okay? int * ptr_to_DAIA; // pointer to dynamically allocated integer array ptr_to_DAIA =...
7
by: Fabian Wauthier | last post by:
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: ...
4
by: terry | last post by:
Hi, Could anyone tell me how to determine the size of array of characters dynamically? For example, : : char *a={"hello","hi","kitty"}; char *b={"orange","apple"};
5
by: nmtoan | last post by:
Hi, I could not find any answer to this simple question of mine. Suppose I have to write a program, the main parts of it are as follows: #include <blahblah.h> struct {
12
by: shalakasan | last post by:
Hi, I am creating a pointer to char: char * lDirName = new char; I am trying to set values character by character. lDirName= 'c'; lDirName= ':'; lDirName= '\\'; The problem is that, the...
11
by: skumar434 | last post by:
Hi everybody, I am faceing problem while assigning the memory dynamically to a array of structures . Suppose I have a structure typedef struct hom_id{ int32_t nod_de; int32_t hom_id;
0
by: pereges | last post by:
On Jun 27, 11:42 pm, j...@smof.fiawol.org (J. Cochran) wrote: ok i will post some code and explanation.
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.