Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Need help with calloc 1

Status
Not open for further replies.

bobbek

Programmer
Mar 11, 2005
2
BG
Hi everyone,

I'm going to tell you how I think calloc() works. If I'm wrong, and I think I am because it doesn't work the way I expect, PLEASE try to explain where my mistake is. Thank you all in advance!

So what we have is void *calloc( size_t num, size_t size );

According to me, the later means:

"Allocate memory block with size 'num * size'. I expect that this memory block is divided into 'num' smaller blocks, 'size' bytes each. So I expect to be able to fill this big block with say 'num' strings, each of them with size 'size'.

Simple example to make it clearer:

char *base = (char *)calloc( 3, 10 * sizeof(char));
base[0] = "123456789";
base[1] = "123456789";
base[2] = "123456789";

When I try to compile this with gcc version 3.3 on MacOS X I get the following mistake:
lea:~/Documents admin$ gcc -o memtest1 memtest1.c
memtest1.c: In function `main':
memtest1.c:5: warning: assignment makes integer from pointer without a cast
memtest1.c:6: warning: assignment makes integer from pointer without a cast
memtest1.c:7: warning: assignment makes integer from pointer without a cast

Help me. Tell me where I am wrong! Thank you once again!
 
No, it's wrong.

Yes, calloc() allocates m*n bytes (and fills it with zeroes) but it's a single continuous block without any subblocks.
I don't know what do you want (exactly). If you want to allocate 3 memory blocks for 3 c-strings, you may:
Code:
char* base[3];
int i;
for (i = 0; i < 3; ++i)
{
    strcpy(base[i] = malloc(10),"123456789");
}
Dont't forget about free() on these 3 pointers.
 
Well, I guess you're right. I got to the idea of the "subblocks" while reading this:

void *calloc(size_t n, size_t s) - Allocates space for n objects of size s. The space is initialised to all bits zero.

I found the later here:

But I still can find any use of this function, besides initializing all bits with zero.
I think I'll stick to malloc, but there's something in the above definition of calloc that still makes me think of that subblocks... I'll have to do some serious reading on the subject!!!
 
Code:
calloc(num, size)
is, as far as I know, roughly equivalent to
Code:
buffer = malloc(num * size);
memset(buffer, 0, num * size);
It probably provides the library more opportunity for optimization, as well.

If I modify ArkM's example to use [tt]calloc[/tt], it may clear up your understanding regarding "sub-blocks":
Code:
char (* buffer)[STR_SIZE] = calloc (NUM_STRS, STR_SIZE);
int i;

for (i = 0; i < NUM_STRS; ++i)
    strncpy (buffer[i], "123456789", STR_SIZE - 1);

That funny-looking declaration [tt]char (* buffer)[STR_SIZE][/tt] just means it's a pointer to objects of type [tt]char[STR_SIZE][/tt]. That's significant because it means that when using the pointer as an array, the elements are [tt]sizeof( char [STR_SIZE] )[/tt] bytes long.

If that type confuses you, try this example instead:
Code:
struct foo
{
    int bar;
    double baz;
};

struct foo *buffer = calloc(NUM_FOOS, sizeof( struct foo ));
int i;

for (i = 0; i < NUM_FOOS; ++i)
{
    buffer[i].bar = 5;
    buffer[i].baz = 1.5;
}

Of course, when you're going to initialize storage to something other than all zeros, as shown in these examples, using [tt]calloc[/tt] was a waste in the first place, and you'd have been better off just using [tt]malloc[/tt].
 
The use of calloc is pretty limited.

Re the tutorial link posted bobbek
"* The value returned from the function calloc() is cast to a suitable type. This is normal practice when using this function since it's default return value is a generic pointer and there are no default conversions between pointer types in C."
This is of course complete hogwash!
In ANSI-C, void* to mytype* pointer conversions are automatic, not casting required.


--
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top