What are malloc( ) and calloc( )?
Simply putting they are the predefined
functions in C language.
Malloc( ) and calloc( ) are two
such functions which are used for more or less identical purpose and that is to
allocate memories for any variable dynamically during execution time of the
program.
Give me a brief of malloc( ).
So as I have said malloc is a function;
malloc must have three valid components as all other functions do have. These
are (a) function name (b) function arguments and (c) function return type, that
is, malloc must have a signature or prototype. Now what is the prototype of
malloc? It is like following:
(void*) malloc(unsigned int) [Note: The actual prototype is slightly
different than this, but for the time being this simplification will work]
It shows that the function name
is malloc itself, it expects an unsigned integer as argument and it returns a
void pointer or generic pointer. So let
us discuss a bit about them.
As per the prototype, malloc
expects an unsigned integer. To assimilate this, let us recall why should we
use malloc? Malloc is used to allocate a chunk of memory at program run time
dynamically. So we must let malloc know what the size of that chunk of memory
is. Suppose we want malloc to allocate a chunk of memory where we can store 10 integers.
In this case, we actually want malloc to allocate 20 bytes of memory (if we are
running our program on windows). And we do it by supplying the size 20 as an
argument. So the unsigned integer that is passed to malloc is actually the
requirement of memory in bytes; and it is evident that the memory requirement cannot
be negative any time, so the data type is unsigned.
Now what that void pointer is
doing at the beginning as return type? To understand this, we have to recall
that a function gives a feedback to its caller through the return type. So
after allocating the memory (I admit, you do not how) malloc has to return the
base pointer, I,e, the address of the starting location of the memory chunk
allocated. Though void pointer, malloc actually returns this base address.
I am sure you will scream out “why
void?” Wait a minute. Answer me, who has written this malloc function? Is it
you or someone else? Obviously it is not you, malloc function is written by someone
else. Now the original developer of malloc had no idea for which purpose you
would be using this malloc. Currently, you can use malloc to allocate memory
for storing some integers, or some floats or some structures defined by you.
There are so many options and those options are equally likely for you. You as
a programmer currently know that this malloc is being used for storing some
integers or whatever else, but the original programmer had no idea about that.
So malloc returns void pointer or generic pointer, a special one which can
point to any type of memory generically. So it is your responsibility to
properly type cast this void pointer. If you are using it to store some
integers, cast void* as int*, if you are using malloc to store some Node type
structures, then cast it to Struct Node*. Got it?
One last point still exists. You must
have seen malloc argument to contain sizeof(), right? Why it is so?
As I have mentioned that the
memory requirement is informed through the argument, it is highly possible that
the memory requirement may change as the OS changes. For example in one system
you may require 20 bytes to store 10 integers, while it may be 40 bytes in
other system or OS. So if I hardcode my memory requirement as 20 or 40 for any
specific platform, it won’t suffice the scenarios generated by other systems.
So to meet the portability issue, that may rise up later, we as a programmer
should not deal with the memory requirement directly. We should inform the
compiler that that we need to store n number
of elements only and let the compiler decide what the size of each such element
is by using sizeof.
So we should call malloc with an
argument (n * sizeof(int)) if we want to store n number of integers. By doing
this, we are actually letting the C compiler to calculate the memory
requirement (under the current OS) of one element and multiplying this with n,
compiler can compute the exact memory requirement as per the current system.
As a good programmer you
should never hardcode your memory requirement, it may end up in a serious
problem if your program gets ported to any other OS.
Look at the following example for clear undestanding:
To store 15 characters, do like
char *pointerToCharArray;
int size = 15;
pointerToCharArray = (char*)malloc(size*sizeof(char));
To store n numbers of MyStructure type of structure, do like
struct MyStructure *pointerToMyStructureArray;
pointerToMyStructureArray = (struct MyStructure*)malloc(n*sizeof(struct
MyStructure));
To store k numbers of integers, do like
int* point;
point = (int*)malloc(k*sizeof(int));
Once you are done with these, you
can use your pointer (like pointerToCharArray
or pointerToMyStructureArray or point as seen in the examples) like an
array with indexing. That means now point[5] will give you the integer stored at 5th
index of point or the sixth integer stored within the memory chunk, base
address of which, is being pointed by a pointer point.
Huh! I finish it off here!
So what is calloc then? How it
is different from malloc?
Calloc is another function which, like malloc,
is used for dynamic memory allocations.
Malloc if called to allocate a
memory space that can store 10 integers (under windows),occupies the memory as a
single chunk of 20 bytes, where calloc, if called for the same purpose,
occupies 20 bytes, but not as a single chunk of memory, rather , it occupies 10
blocks of memory, each having 2 bytes (as it is under windows, as we have
supposed). Hence calloc has the following prototype:
(void*) calloc(unsigned int, unsigned int)
The first unsigned int is for number of elements that you want to store and
the second unsigned int is for memory
allocation needed for storing a single element.
This is why calloc can occupy the
memory space with multiple blocks, each of equal size. The void* is doing the same
thing as that of malloc
So look at the following example for clear understanding:
To store 15 characters, do like
char *pointerToCharArray;
int size = 15;
pointerToCharArray = (char*)calloc(size, sizeof(char));
To store n numbers of MyStructure type of structure, do like
struct MyStructure *pointerToMyStructureArray;
pointerToMyStructureArray = (struct MyStructure*)calloc(n, sizeof(struct
MyStructure));
To store k numbers of integers, do like
int* point;
point = (int*)calloc(k, sizeof(int));
So the syntactical difference is
malloc takes one argument, while calloc takes two. But you need to have an idea
why it is so. I think the above discussion tells you that.
Another point of difference is
like following:
Malloc allocates the memory chunk
and initializes the memory with garbage values, whereas calloc allocates the
multiple block of memory chunks and initializes those with 0s (zeros)
So we come to an end of this
discussion. I am open to clear your doubts if any.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.