tags:

views:

213

answers:

4

I am writing the calloc function in a memory management assignment (I am using C). I have one question, I wrote the malloc function and thinking about using it for calloc as it says calloc will take num and size and return a block of memory that is (num * size) which I can use malloc to create, however, it says that I need to initialize all bytes to 0 and I am confused about how to do that in general? If you need more info please ask me :)

So malloc will return a pointer (Void pointer) to the first of the usable memory and i have to go through the bytes, initialize them to zero, and return the pointer to that front of the usable memory.

+2  A: 

When you need to set a block of memory to the same value, use the memset function.

It looks like this: void * memset ( void * ptr, int value, size_t num );

You can find more information about the function at: http://www.cplusplus.com/reference/clibrary/cstring/memset/

Aeolien
What if I also need to write memset myself, how would I write it? (I am looking at the link right now sorry if the link gives this information)
A: 

Hints:

  • there is already a posix library function for zeroing a block of memory

  • consider casting the void * to some pointer type that you can dereference / assign to.

Stephen C
+4  A: 

I am assuming you can't use memset because it's a homework assignment assignment, and deals with memory management. So, I would just go in a loop and set all bytes to 0. Pseudocode:

for i = 1 to n:
   data[i] = 0

Oh, if you're having trouble understanding how to dereference void *, remember you can do:

void *b;
/* now make b point to somewhere useful */
unsigned char *a = b;
Alok
Actually you are right i am not allowed to use memset, however, my problem is sitting the memory to 0, i know i have to loop it and set every byte to zero using char ( so i can move one byte a time ) but i am not sure how to use that to set it to zero ...
Just assign each byte to 0.
Alok
(unsigned) char is an integral type, and the C standard guarantees that all bits 0 represents 0 for such types. Is that what's confusing you?
Alok
I understand that u loop over the memory but I still don't get how you assign a byte to be zero, do u just say currentLocaion (saying it is a char*) and that equals to zero then currentLocation++ to move to the next byte of memory and u do that or that's not what we do?
Yes. So I can say: unsigned char *a = b; for(i=0; i < n; ++i) a[i] = 0;
Alok
why do you have to say [ ] ? is that something you have to say no matter what? can't we just say while ( size -- ) { *a++ = 0 } mentioning that a is just char* a = (char*) b; ?Thanks so much for your help :)
You can't say char a = (char *)b, because a is a char and b is a pointer. In C, if "a" is a pointer, and a[i], is the same as *(a+i), which is the value at the location pointed by "a+i". You want to set that value to 0 for all i in the range 0 to n (not including n). Is this clear?
Alok
ohh i meant char* a. ohh i c, thanks
I think in your pseudocode you should consider using `0` and `(n-1)` as the limits of the for loop range - I know you're trying to make the answer a bit 'indirect' due to it being a homework problem, but seasoned programmers get indexes off by one enough times that I think using a 1-based index in the pseudocode is plain misleading (and maybe even unfair) to a beginner.
Michael Burr
+1  A: 

If you can't use memset, then you'll need to resort to setting each byte individually.

Since you're calling malloc from your calloc function, I'm going to assume it looks something like this:

void *calloc (size_t count, size_t sz) {
    size_t realsz = count * sz;
    void *block = malloc (realsz);
    if (block != NULL) {
        // Zero memory here.
    }
    return block;
}

and you just need the code for "// Zero memory here.".

Here's what you need to know.

  1. In order to process the block one byte at a time, you need to cast the pointer to a type that references bytes (char would be good). To cast your pointer to (for example) an int pointer, you would use int *block2 = (int*)block;.

  2. Once you have the right type of pointer, you can use that to store the correct data value based on the type. You would do this by storing the desired value in a loop which increments the pointer and decrements the count until the count reaches zero.

Hopefully that's enough to start with without giving away every detail of the solution. If you still have problems, leave a comment and I'll flesh out the answer until you have it correct (since it's homework, I'll be trying to get you to do most of the thinking).

Update: Since an answer's already been accepted, I'll post my full solution. To write a basic calloc in terms of just malloc:

void *calloc (size_t count, size_t sz) {
    size_t realsz, i;
    char *cblock;

    // Get size to allocate (detect size_t overflow as well).

    realsz = count * sz;
    if (count != 0)
        if (realsz / count != sz)
            return NULL;

    // Allocate the block.

    cblock = malloc (realsz);

    // Initialize all elements to zero (if allocation worked).

    if (cblock != NULL) {
        for (i = 0; i < realsz; i++)
            cblock[i] = 0;
    }

    // Return allocated, cleared block.

    return cblock;
}

Note that you can work directly with char pointers within the function since they freely convert to and from void pointers.

paxdiablo
you will have to say cblock = (void*) cblock before you return it because u need to return a void pointer :) but thanks for the code :)
@c2009l1: No, you won't have to do anything like that. Casts to `void *` are performed implicity in C (in C++ as wll, BTW). Additionaly, doing `cblock = (void *) cblock` makes no sense at all. Why would you cast it and then assign to the same variable?
AndreyT
@paxdiablo: I don't know if you were trying to make it as correct as possible, but a correct implementatiom of `calloc` also has to make sure that the multiplication `count * sz` doesn't overflow.
AndreyT
@AndreyT, I did think of that but, since it's simple homework, I left it out, which is why I explicitly put the "basic" adjective in there because of that. @c2009l1, make sure you don't use code verbatim from the net for homework. You would be unwise to think your educators do not look out for this. That's why I have little concern with answering SO homework questions with a bit of code nowadays - if people are silly enough to use it without understanding (and changing), they deserve to fail :-)
paxdiablo
Since you have now put in an overflow check: 0 is legal for either input.
Steve Jessop
Good point and easily fixed by not doing the divide check when count is zero. Everything else still works since the realsz will be zero for either of your cases and allocating zero bytes is valid.
paxdiablo