2D array of structures

S

svata

Hello,

I wonder how to resize such array of structures using realloc()?

#include <stdio.h>
#include <stdlib.h>
#define FIRST 7

typedef struct {
char *name;
int i;
int j;
} STRUCTURE;

STRUCTURE **p_structure;

int main() {

p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));
if ( p_structure == NULL ) {
printf("Failed to allocate memory, exiting...");
return 1;
}
}

Thank you in advance

Svata
 
J

Jens Thoms Toerring

svata said:
I wonder how to resize such array of structures using realloc()?
#include <stdio.h>
#include <stdlib.h>
#define FIRST 7
typedef struct {
char *name;
int i;
int j;
} STRUCTURE;
STRUCTURE **p_structure;
int main() {

Make that

int main( void )

since your main() takes no arguments.
p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));

Don't cast the return value of malloc(), it only hides your mistake
should you have forgotten to include <stdlib.h>. But, more important,
you allocate here memory for 7 (FIRST) such structures. malloc() returns
a pointer to the start of this memory, which is of type 'STRUCTURE *'
(malloc() actually returns a void pointer but "STRUCTURE *' is the
correct type of a pointer to that memory). But you assign it instead
to a pointer that has type 'STRUCTURE **'. That, combined with your
use of the words "2D array" in the subjct line, leads to the suspicion
that you actually don't want to allocate memory for something that has
similar properties as an array of stuctures, but something more compli-
cated and similar to a 2D array of such structures. And that's what you
definitely won't get with that allocation, whatever the type of the
pointer you assign the return value of malloc() to. So, instead of
starting to guess what you might have intended I think it's better to
ask you to specify a bit more clearly what you intend to do here: do
you just want memory for a simple set of structures or do you want
something like a 2D array of such structures. In the first case you
could "repair" your program by simply defining 'p_structure' as

STTRUCTURE *p_structure;

Perhaps you thenn also might want to replace the line for the allo-
cation by

p_structure = malloc(FIRST * sizeof *p_structure);

because that way you don't have to change that line anymore if you
should decide to change the type of 'p_structure' sometime later.

You also write something about realloc() but I can't see any
use or mentioning of realloc() in the code you posted. But, of
course, you can use realloc() to resize the amount of memory
you obtained from malloc() - that's what realloc() was invented
for.
if ( p_structure == NULL ) {
printf("Failed to allocate memory, exiting...");
return 1;
}

It's good to see that you check that what malloc() returned!

Since main() returns an int, here's a missing line with a return
value...
Regards, Jens
 
F

Flash Gordon

correct type of a pointer to that memory). But you assign it instead
to a pointer that has type 'STRUCTURE **'. That, combined with your
use of the words "2D array" in the subjct line, leads to the suspicion
that you actually don't want to allocate memory for something that has
similar properties as an array of stuctures, but something more compli-
cated and similar to a 2D array of such structures. And that's what you

<snip>

I agree with what you've said, but the OP should also read section 6 of
the comp.lang.c FAQ before posting back here. Section 6 includes ways of
dynamically allocating space for things that work like 2D arrays. The
FAQ can be found at http://c-faq.com/
 
F

Frederick Gotham

svata:
STRUCTURE **p_structure;


This is a pointer to a pointer to a STRUCTURE.

(I'm against the use of ALL CAPS for anything other than macros)

int main() {

p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));


This doesn't make sense.

You have a pointer to a pointer to a STRUCTURE. This would suggest to me
that you're going to store either of the following in it:

(1) The address of a pointer to a STRUCTURE.
(2) The address of the first element of an array, whereby each element
is a pointer to a STRUCTURE.

If it were either of the two above, the "malloc" invocation should look
something like:

p_structure = malloc( sizeof(STRUCTURE*) );
or:
p_structure = malloc( 12 * sizeof(STRUCTURE*) );

Note that I use the size of a "STRUCTURE*" rather than the size of a
"STRUCTURE".

Of course, it's better to write the two of them as:

p_structure = malloc(sizeof*p);

p_structure = malloc(12 * sizeof*p);
 
C

CBFalconer

svata said:
I wonder how to resize such array of structures using realloc()?

#include <stdio.h>
#include <stdlib.h>
#define FIRST 7

typedef struct {
char *name;
int i;
int j;
} STRUCTURE;

STRUCTURE **p_structure;

Too many *s here.
int main() {

You
p_structure = (STRUCTURE **) malloc(FIRST * sizeof(STRUCTURE));

and here. Also _never_ cast the return from malloc (it only hides
errors without fixing them). You want:

p_structure = malloc(FIRST * sizeof *p_structure);
if ( p_structure == NULL ) {
printf("Failed to allocate memory, exiting...");
return 1;
}
}

You can then change the size to, say, SECOND with:

STRUCTURE *tmp; /* in a suitable location, not here */

if (tmp = realloc(p_structure, SECOND) p_structure = tmp;
else {
/* handle lack of memory */
}
 
S

svata

Hello Frederick,

I know it doesn't make sense. I was wrong in my assumption.
I should use p_structure = (STRUCTURE **) malloc(FIRST *
sizeof(STRUCTURE*));

but anyway... should rather use array of structures.


typedef structure {
code goes here...
} _structure;

_structure *p_structure;
// and then malloc()

p_structure = malloc( INT * sizeof(_structure));

if am I right?

svata

Frederick said:
This is a pointer to a pointer to a STRUCTURE.

(I'm against the use of ALL CAPS for anything other than macros)




This doesn't make sense.
 
C

Chris Dollin

svata said:
Hello Frederick,

I know it doesn't make sense. I was wrong in my assumption.
I should use p_structure = (STRUCTURE **) malloc(FIRST *
sizeof(STRUCTURE*));

No, you shouldn't: it's wiser to drop the unnecessary cast an
to ensure that the thing you sizeof is appropriate for the
pointer:

pStructure = malloc( FIRST * sizeof (*pStructure) );

which will (try to) mallocate space for FIRST (horrid name)
lumps of space adequate for the kinds of thing that
pStructure points to.
but anyway... should rather use array of structures.

Yes, get rid of the unnecessary layer of indirection.
typedef structure {
code goes here...
} _structure;

There are two things wrong with this. One is that it's
syntax is broken, since you spelt "struct" "structure".
The other is that so many names beginning with _ are
reserved to the implementation it's unwise for you to
define /any/ name that does. So don't.

If you /must/ use a typedef for a structure -- you don't
need to, and some wise people argue that you shouldn't
(although others argue that those arguments aren't
convincing) -- you should also give it a /sensible/
name. "structure" isn't.

typedef struct yourStructTagHere
{
int x;
int y;
} Point;
 
S

svata

I always use google to search an answer, but often results are not
relevant.


svata
 
R

Richard Heathfield

svata said:
Chris Dollin wrote:

I learn by doing. So I will see what results I get.

That's fine sometimes, but there are also times when it's best to learn from
other people's knowledge and experience. If you learn C "by doing", you're
likely to end up doing lots of things that aren't correct, but which happen
to behave in a particular way on your current system. Switch systems, and
all your code breaks. Oops.

Chris is an expert on C. Listen to Chris.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
C

Chris Dollin

Richard said:
svata said:

Something happend to your quoting, Richard: it looks like it was me that
said "I learn by doing. So I will see what results I get.", but it was
svata.

(svata's quoting was misleading anyway, since he half-top-posted.)
That's fine sometimes, but there are also times when it's best to learn from
other people's knowledge and experience. If you learn C "by doing", you're
likely to end up doing lots of things that aren't correct, but which happen
to behave in a particular way on your current system. Switch systems, and
all your code breaks. Oops.

Chris is an expert on C.

I'd hesitate to describe myself so, since there's so much C I don't
know (most of the C99 stuff, for example!) and I've used it in so
few environments. I know /some/ stuff about C. I hope it's useful
stuff.
Listen to Chris.

But not when I'm singing.
 
C

Chris Dollin

CBFalconer said:
Like me, you appear to be a member of the 'crows in heat' chorus.

Very likely. Or hedgehogs ... snuffling. Perhaps we should
characterise Undefined Behaviour as "Chris or <your preferred
abbreviation> will sing for/at you". /That/ will worry them
more than hyperbolic nasal demons.
 
R

Richard Heathfield

Chris Dollin said:
Something happend to your quoting, Richard:

No, just a snip slip. Sorry about that.
I'd hesitate to describe myself so,

Think "relative". Compared to most OPs around here, you're a towering
genius!

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
F

Frederick Gotham

svata:
Hello Frederick,


Hello svata :)

I know it doesn't make sense. I was wrong in my assumption.
I should use p_structure = (STRUCTURE **) malloc(FIRST *
sizeof(STRUCTURE*));

but anyway... should rather use array of structures.


typedef structure {
code goes here...
} _structure;

_structure *p_structure;


One thing that you'll notice as you program more and more is that you'll
come to use abbreviations (most programmers do in anyway). Humans love
shortcuts. "should have" became "should've", which became "shuda". The
words "until" and "because" are slowly but surely becoming "til" and
"cause".

When I myself define a pointer variable, I simply prefix "p" to the name; I
used to put an underscore with it too but then more months passed by and I
got lazier and lazier. The variable name "p_structure" is a bit of a
mouthful, maybe you'd prefer to keep the names small.

There are a few different prevalent coding styles out there. My own style
works as follows:

(1) Functions and Types start with a capital letter. If it consists of more
than one word, than the next word starts with an initial capital, e.g.

void TruncateLastFiveDigits(char*);

(2) Objects start with a lower case letter. If it consists of more than one
word, then underscores are used, e.g.

int len_main_str = 34;

(3) For a pointer, I prefix a simple "p" to the name where possible:

void (*pFunc)(int) = Func;
void (**ppFunc)(int) = &pFunc;

int *pobj = &obj;
int **ppobj = &pobj;
int ***pppobj = &ppobj;

(4) Macro names are in ALL CAPS. No other name should be written in ALL
CAPS, e.g.:

#define LEN 5
#define SQR(x) ((x)*(x))

Of course, this is just my own style. I'm not trying to shove it down your
throat, but I'm just suggesting it as I thought you might like it.

// and then malloc()

p_structure = malloc( INT * sizeof(_structure));

if am I right?


Yes, you're right. It's handy though to not have to repeat the name of the
type:

int *const p = malloc(5 * sizeof(int));

can be written as:

int *const p = malloc(5 * sizeof*p);

Now, if we change the type to double, we only have to change "p":

double *const p = malloc(5 * sizeof*p);

Here's a taste of how I might write the code:

#include <stddef.h> /* To use "size_t" */
#include <stdlib.h> /* To use "malloc" and "free" */

typedef struct MyStruct {
int i;
} MyStruct;

size_t GetNumberFromSomewhere(void); /* Defined elsewhere */

int main(void)
{
size_t const len = GetNumberFromSomewhere();

MyStruct *const p = malloc(len * sizeof*p);

/* ... */

free(p);

return 0;
}
 
F

Flash Gordon

svata wrote:

Please do not top post. Your reply belongs under the text you are
replying to, not above.
> I always use google to search an answer, but often results are not
> relevant.

I did not suggest using Google, I suggested a specific resource and a
particular area in it. From another post here it is obvious you have not
followed that advice, and if you don't bother following advice or
posting properly I see no reason to bother giving you advice.
 
C

CBFalconer

Frederick said:
.... snip ...

One thing that you'll notice as you program more and more is that
you'll come to use abbreviations (most programmers do in anyway).
Humans love shortcuts. "should have" became "should've", which
became "shuda". The words "until" and "because" are slowly but
surely becoming "til" and "cause".

Not the smarter ones. They try to stick to English, and remain
fairly clear to their readers. Should've is legitimate English,
shuda is an execresence. Misuse of the word 'cause' causes nothing
but confusion.
 
K

Keith Thompson

Chris Dollin said:
If you /must/ use a typedef for a structure -- you don't
need to, and some wise people argue that you shouldn't
(although others argue that those arguments aren't
convincing) -- you should also give it a /sensible/
name. "structure" isn't.

typedef struct yourStructTagHere
{
int x;
int y;
} Point;

There's also no need to use different identifiers for the struct tag
and the typedef name:

typedef struct Point {
int x;
int y;
} Point;

Now you can refer to the type either as "Point" or as "struct Point".

The purpose of the typedef is to allow you to use a single identifer
to refer to the type. The argument Chris alluded to above *against*
using a typedef is that gives a second name to a type that already has
a perfectly good name. For example, I would have declared it as:

struct Point {
int x;
int y;
};

and just refer to the type as "struct Point".

But plenty of smart people prefer to use the typedef. And if your
structure doesn't contain any pointers to itself (as for a linked list
node, for example), you don't need the struct tag:

typedef struct {
int x;
int y;
} Point;

The drawback of this is that the name "Point" doesn't become visible
until the end of the declaration, so you can't declare a member of
type Point*.
 
R

Richard Heathfield

Keith Thompson said:
There's also no need to use different identifiers for the struct tag
and the typedef name:

typedef struct Point {
int x;
int y;
} Point;

It's true that there's no C reason to use different identifiers, but I do so
anyway because it helps Microsoft's "Intellisense" to work out what you
mean when you hit the button that says "take me to your definition". Not
that I use Microsoft C terribly often - but when I do, I usually end up
thanking myself for using a unique tag name. My preferred style nowadays
is:

struct foo_
{
char coal;
short wait;
unsigned letter;
long time;
float away;
double trouble;
bar baz;
ad nauseam;
};

typedef struct foo_ foo;

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top