calloc

K

Koster

Sorry for the re-post, but my previous question was left unanswered.

I have a question about the appropriateness of calloc. Consider an array of
pointers to structs which need to be allocated space on the heap, for example:

typedef struct myStruct *PMYSTRUCT;
struct myStruct
{
int i;
int j;
...etc...
}

PMYSTRUCT myArray[10];

While I know I can point and allocate each element manually my looping mallocs,
I wonder if calloc will do what I want. Will executing "myArray = calloc(10,
sizeof(myStruct));" allocate 10 myStructs somewhere on the heap and put pointers
to each one in the myArray array, or will it allocate the myStructs and point
myArray[0] to it, thereby making myArray[1] point somewhere inside the 1st
myStruct and messing up everything?

I hope that's clear enough,
Koster.
 
A

Arthur J. O'Dwyer

I have a question about the appropriateness of calloc. Consider an array
of pointers to structs which need to be allocated space on the heap, for
example:

typedef struct myStruct *PMYSTRUCT;
struct myStruct
{
int i;
int j;
...etc...
}

PMYSTRUCT myArray[10];

Better if you have a question *not* to use this sort of obfuscating
typedef. I started this response intending to point out that 'myArray'
was *already* an array of 'myStruct', so you couldn't assign anything
to it. In fact, it's an array of *pointers* to 'myStruct' -- so you
still can't assign anything to it, but you *do* have to initialize the
elements correctly.
Writing

struct myStruct *myArray[10];

would have made your question (and your code) much clearer.
While I know I can point and allocate each element manually [by] looping
mallocs, I wonder if calloc will do what I want. Will executing
"myArray = calloc(10, sizeof(myStruct));" allocate 10 myStructs somewhere
on the heap and put pointers to each one in the myArray array, or will
it allocate the myStructs and point myArray[0] to it, thereby making
myArray[1] point somewhere inside the 1st myStruct and messing up
everything?

Neither. It won't compile. Try it and see.

What you want, in essence, is to allocate some memory for each of
the pointers to point to. You want

myArray[0] = malloc(sizeof *myArray[0]);
myArray[1] = malloc(sizeof *myArray[0]);
myArray[2] = malloc(sizeof *myArray[0]);
myArray[3] = malloc(sizeof *myArray[0]);
...
myArray[9] = malloc(sizeof *myArray[0]);


Now, you can of course put that inside a loop:

for (i=0; i < 10; ++i)
myArray = malloc(sizeof *myArray);

...
for (i=0; i < 10; ++i) /* free each block */
free(myArray);


Or you can merge all the memory allocations into one big chunk:

myArray[0] = malloc(10 * sizeof *myArray[0]);
for (i=0; i < 10; ++i)
myArray = myArray[0] + i;

...
free(myArray[0]); /* free the big chunk directly */


The first way is easier IMHO; the second, big-chunk way may
be more efficient if you are doing a lot of memory allocation.

Oh, and about 'calloc': As a general rule, don't use it for
structs. Don't use it for anything, really, because it often
doesn't do anything more useful than 'malloc'.
'calloc' zeroes out all the bits in the allocated chunk of
memory. This makes it good for initializing 'unsigned char's,
but that's just about all. All-bits-zero is *not* guaranteed
to be anything useful with respect to pointers, floating-point
numbers, or even regular old integers(!). So 'calloc' isn't
very useful. Use 'malloc' instead.

HTH,
-Arthur
 
B

Bertrand Mollinier Toublet

Koster said:
I have a question about the appropriateness of calloc. Consider an array of
pointers to structs which need to be allocated space on the heap, for example:
The standard C language has no notion of heap (which gives too much
detail about implementation details). It speaks of allocated storage
duration. As I said, this can be implemented as a heap, but it is not
guaranted nor necessary.
typedef struct myStruct *PMYSTRUCT;

It is usually not a good idea to hide that a type is actually a pointer
type. I would rather advise, for example, and notwithstanding the
invasion of the POSIX reserved namespace:

typedef struct myStruct myStruct_t;
struct myStruct
{
int i;
int j;
...etc...
}; /* <-- note the required ; */
PMYSTRUCT myArray[10];
myStruct_t *myArray[10];
While I know I can point and allocate each element manually my looping mallocs,
I wonder if calloc will do what I want. Will executing "myArray = calloc(10,
sizeof(myStruct));" allocate 10 myStructs somewhere on the heap and put pointers
to each one in the myArray array, or will it allocate the myStructs and point
myArray[0] to it, thereby making myArray[1] point somewhere inside the 1st
myStruct and messing up everything?
Second option. malloc and calloc behave essentially the same, with one
exception. The standard says:

7.20.3.1 The calloc function
Synopsis
1 #include <stdlib.h>
void *calloc(size_t nmemb, size_t size);
Description
2 The calloc function allocates space for an array of nmemb objects,
each of whose size is size. The space is initialized to all bits
zero. 252)

And note 252 says:

252) Note that this need not be the same as the representation of
floating-point zero or a null pointer constant.

On the other hand, for malloc, we have:

7.20.3.3 The malloc function
Synopsis
1 #include <stdlib.h>
void *malloc(size_t size);
Description
2 The malloc function allocates space for an object whose size is
specified by size and whose value is indeterminate.

So the only difference between malloc and calloc (besides the argument
format) is that calloc also initializes the storage to all bits 0. Given
note 252, this is not even very useful, so that in practice you have
almost no reason to use calloc...
I hope that's clear enough,

Same here :)
 
J

Jens.Toerring

Koster said:
I have a question about the appropriateness of calloc. Consider an array of
pointers to structs which need to be allocated space on the heap, for example:

Where the system will allocate space for you shouldn't be of any
concern for you as long as you're writing portable C;-)
typedef struct myStruct *PMYSTRUCT;
struct myStruct
{
int i;
int j;
...etc...
}
PMYSTRUCT myArray[10];
While I know I can point and allocate each element manually my looping mallocs,
I wonder if calloc will do what I want. Will executing "myArray = calloc(10,
sizeof(myStruct));" allocate 10 myStructs somewhere on the heap and put pointers
to each one in the myArray array, or will it allocate the myStructs and point
myArray[0] to it, thereby making myArray[1] point somewhere inside the 1st
myStruct and messing up everything?

First of all, since you has made PMYSTRUCT to be a *pointer* to
struct myStruct, the line

PMYSTRUCT myArray[10];

will give you an array of ten such *pointers*. It's as if you had written

struct myStruct *myArray[ 10 ];

When you then try to do an assignment as in

myArray = calloc( 10, sizeof( myStruct ) );

your compiler should complain loudly because your 'myArray' can't be
used unadorned as a left hand side value - only when used on the right
hand side or as part of an expression it decays into a pointer to the
first element of the array. So you need either

*myArray = calloc( 10, sizeof( myStruct ) );

or, equivalently,

myArray[ 0 ] = calloc( 10, sizeof( myStruct ) );

to assign to the first element of the array 'myArray'. Of course, when
you do this all the other nine elements will still point to some random
places in memory.

You have two alternatives. First, change the typedef to

typedef struct myStruct PMYSTRUCT;

so that PMYSTRUCT does not translate to a pointer to a myStruct
structures but to 'struct myStruct' itself. Then

PMYSTRUCT myArray[10];

will give you an array of 10 such structures with all memory already
attached, so you don't have to use calloc() or malloc().

Or, if you insist on

typedef struct myStruct *PMYSTRUCT;

use

PMYSTRUCT myArray;

(But then I still would prefer

typeded struct myStruct MYSTRUCT;
MYSTRUCT *myArray;

so you always know if you're dealing with a real structure or a pointer,
instead of having the "pointerness" of it hidden, which in my opinion
makes reading code much more difficult). Then you can allocate memory
with

myArray = calloc( 10, sizeof *myArray );

and you now can treat myArray basically like an array of 10 strutctures,
i.e. you can get at the member 'i' of the 5th structure with
'myArray[ 4 ].i' etc.
Regards, Jens
--
_ _____ _____
| ||_ _||_ _| (e-mail address removed)-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring
 
?

=?ISO-8859-1?Q?Johan_Aur=E9r?=

'calloc' zeroes out all the bits in the allocated chunk of
memory. This makes it good for initializing 'unsigned char's,
but that's just about all.

Just about. AAMOF, any character type will work (and as Jack Klein
pointed out recently, so will C99's intN_t and uintN_t types).
 
K

Koster

On 11 Sep 2003 15:33:00 GMT, (e-mail address removed)-berlin.de wrote:

|> I have a question about the appropriateness of calloc. Consider an array of
|> pointers to structs which need to be allocated space on the heap, for example:
|
|Where the system will allocate space for you shouldn't be of any
|concern for you as long as you're writing portable C;-)

Okay, forget the part about the heap. It's irrelevant anyway.

|> typedef struct myStruct *PMYSTRUCT;
|> struct myStruct
|> {
|> int i;
|> int j;
|> ...etc...
|> }
|
|> PMYSTRUCT myArray[10];
|

<snip>

|
|First of all, since you has made PMYSTRUCT to be a *pointer* to
|struct myStruct, the line
|
|PMYSTRUCT myArray[10];
|
|will give you an array of ten such *pointers*. It's as if you had written
|
|struct myStruct *myArray[ 10 ];

That is correct. I'm using an array of pointers to implement a hashtable. I do
not want an array of structs because the number of elements is highly volatile,
and as such I put them in a linked list rather than an array.

|When you then try to do an assignment as in
|
|myArray = calloc( 10, sizeof( myStruct ) );
|
|your compiler should complain loudly because your 'myArray' can't be
|used unadorned as a left hand side value - only when used on the right
|hand side or as part of an expression it decays into a pointer to the
|first element of the array. So you need either

Interestingly then, the MS VC++ compiler compiles the above line without any
problems, although admittedly with a cast to my pointer-to-myStruct typedef. I
see now (and I guess I'm an ass for not noticing it earlier), that it made all
the extensions .cpp for me, and as such it probably accepts a lot of my errors.
I have renamed them all to .c and sure enough it comes up with >60 build errors.

Whoops. It's a hobby project anyway, I can afford to waste time fixing it up :)

|*myArray = calloc( 10, sizeof( myStruct ) );
|
|or, equivalently,
|
|myArray[ 0 ] = calloc( 10, sizeof( myStruct ) );
|
|to assign to the first element of the array 'myArray'. Of course, when
|you do this all the other nine elements will still point to some random
|places in memory.

That's what I needed to know :)
So to allocate a struct for each element in the array to point to, I should just
loop through each and malloc each one individually, storing the returned pointer
in the appropriate array element, and forget about calloc.

<snip>

Thanks,
Koster.
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top