Friday, May 21, 2010

Dynamic Memory Allocation

In programming we may come across situations where we may have to deal with data, which is dynamic in nature. The number of data items may change during the executions of a program. The number of customers in a queue can increase or decrease during the process at any time. When the list grows we need to allocate more memory space to accommodate additional data items. Such situations can be handled move easily by using dynamic techniques. Dynamic data items at run time, thus optimizing file usage of storage space.



Dynamic memory allocation:

The process of allocating memory at run time is known as dynamic memory allocation. Although c does not inherently have this facility there are four library routines which allow this function.

Many languages permit a programmer to specify an array size at run time. Such languages have the ability to calculate and assign during executions, the memory space required by the variables in the program. But c inherently does not have this facility but supports with memory management functions, which can be used to allocate and free memory during the program execution. The following functions are used in c for purpose of memory management.

Function
Task
malloc
Allocates memory requests size of bytes and returns a pointer to the Ist byte of allocated space
calloc
Allocates space for an array of elements initializes them to zero and returns a pointer to the memory
free
Frees previously allocated space
realloc
Modifies the size of previously allocated space.


Memory allocations process:

According to the conceptual view the program instructions and global and static variable in a permanent storage area and local area variables are stored in stacks. The memory space that is located between these two regions in available for dynamic allocation during the execution of the program. The free memory region is called the heap. The size of heap keeps changing when program is executed due to creation and death of variables that are local for functions and blocks. Therefore it is possible to encounter memory overflow during dynamic allocation process. In such situations, the memory allocation functions mentioned above will return a null pointer.

Allocating a block of memory:

A block mf memory may be allocated using the function malloc. The malloc function reserves a block of memory of specified size and returns a pointer of type void. This means that we can assign it to any type of pointer. It takes the following form:

ptr=(cast-type*)malloc(byte-size);

ptr is a pointer of type cast-type the malloc returns a pointer (of cast type) to an area of memory with size byte-size.

Example:

x=(int*)malloc(100*sizeof(int));

On successful execution of this statement a memory equivalent to 100 times the area of int bytes is reserved and the address of the first byte of memory allocated is assigned to the pointer x of type int

Allocating multiple blocks of memory:

Calloc is another memory allocation function that is normally used to request multiple blocks of storage each of the same size and then sets all bytes to zero. The general form of calloc is:

ptr=(cast-type*) calloc(n,elem-size);

The above statement allocates contiguous space for n blocks each size of elements size bytes. All bytes are initialized to zero and a pointer to the first byte of the allocated region is returned. If there is not enough space a null pointer is returned.

Releasing the used space:

Compile time storage of a variable is allocated and released by the system in accordance with its storage class. With the dynamic runtime allocation, it is our responsibility to release the space when it is not required. The release of storage space becomes important when the storage is limited. When we no longer need the data we stored in a block of memory and we do not intend to use that block for storing any other information, we may release that block of memory for future use, using the free function.

free(ptr);

ptr is a pointer that has been created by using malloc or calloc.

To alter the size of allocated memory:

The memory allocated by using calloc or malloc might be insufficient or excess sometimes in both the situations we can change the memory size already allocated with the help of the function realloc. This process is called reallocation of memory. The general statement of reallocation of memory is :

ptr=realloc(ptr,newsize); 
This function allocates new memory space of size newsize to the pointer variable ptr ans returns a pointer to the first byte of the memory block. The allocated new block may be or may not be at the same region.

/*Example program for reallocation*/
#include< stdio.h >
#include< stdlib.h >
define NULL 0
main()
{
char *buffer;
/*Allocating memory*/
if((buffer=(char *) malloc(10))==NULL)
{
printf(“Malloc failed\n”);
exit(1);
}
printf(“Buffer of size %d created \n,_msize(buffer));
strcpy(buffer,”Bangalore”);
printf(“\nBuffer contains:%s\n”,buffer);
/*Reallocation*/
if((buffer=(char *)realloc(buffer,15))==NULL)
{
printf(“Reallocation failed\n”);
exit(1);
}
printf(“\nBuffer size modified.\n”);
printf(“\nBuffer still contains: %s\n”,buffer);
strcpy(buffer,”Mysore”);
printf(“\nBuffer now contains:%s\n”,buffer);
/*freeing memory*/
free(buffer);
}
 

Pointers and Structures


Pointers and structures:

We know the name of an array stands for the address of its zeroth element the same concept applies for names of arrays of structures. Suppose item is an array variable of struct type. Consider the following declaration:

struct products
{
char name[30];
int manufac;
float net;
item[2],*ptr;

this statement declares item as array of two elements, each type struct products and ptr as a pointer data objects of type struct products, the

assignment ptr=item;

would assign the address of zeroth element to product[0]. Its members can be accessed by using the following notation.

ptr- >name;
ptr- >manufac;
ptr- >net;

The symbol - > is called arrow pointer and is made up of minus sign and greater than sign. Note that ptr- > is simple another way of writing product[0].

When the pointer is incremented by one it is made to pint to next record ie item[1]. The following statement will print the values of members of all the elements of the product array.

for(ptr=item; ptr< item+2;ptr++)
printf(“%s%d%f\n”,ptr- >name,ptr- >manufac,ptr- >net);

We could also use the notation

(*ptr).number

to access the member number. The parenthesis around ptr are necessary because the member operator ‘.’ Has a higher precedence than the operator *.

Pointers and Arrays


Pointer to arrays:

an array is actually very much like pointer. We can declare the arrays first element as a[0] or as int *a because a[0] is an address and *a is also an address the form ofdeclaration is equivalent. The difference is pointer is a variable and can appear on the left of the assignment operator that is lvalue. The array name is constant and cannot appear as the left side of assignment operator.

/* A program to display the contents of array using pointer*/
main()
{
int a[100];
int i,j,n;
printf(“\nEnter the elements of the array\n”);
scanf(“%d”,&n);
printf(“Enter the array elements”);
for(I=0;I< n;I++)
scanf(“%d”,&a[I]);
printf(“Array element are”);
for(ptr=a,ptr< (a+n);ptr++)
printf(“Value of a[%d]=%d stored at address %u”,j+=,*ptr,ptr);
}

Strings are characters arrays and here last element is \0 arrays and pointers to char arrays can be used to perform a number of string functions.

Pointers


Introduction:

In c a pointer is a variable that points to or references a memory location in which data is stored. Each memory cell in the computer has an address that can be used to access that location so a pointer variable points to a memory location we can access and change the contents of this memory location via the pointer.

Pointer declaration:

A pointer is a variable that contains the memory location of another variable. The syntax is as shown below. You start by specifying the type of data stored in the location identified by the pointer. The asterisk tells the compiler that you are creating a pointer variable. Finally you give the name of the variable.

type * variable name 
Example:

int *ptr;
float *string;

Address operator:

Once we declare a pointer variable we must point it to something we can do this by assigning to the pointer the address of the variable you want to point as in the following example:

ptr=&num;

This places the address where num is stores into the variable ptr. If num is stored inmemory 21260 address then the variable ptr has the value 21260.

/* A program to illustrate pointer declaration*/

main()
{
int *ptr;
int sum;
sum=45;
ptr=∑
printf (“\n Sum is %d\n”, sum);
printf (“\n The sum pointer is %d”, ptr);
}

we will get the same result by assigning the address of num to a regular(non pointer) variable. The benefit is that we can also refer to the pointer variable as *ptr the asterisk tells to the computer that we are not interested in the value 21260 but in the value stored in that memory location. While the value of pointer is 21260 the value of sum is 45 however we can assign a value to the pointer * ptr as in *ptr=45.

This means place the value 45 in the memory address pointer by the variable ptr. Sincethe pointer contains the address 21260 the value 45 is placed in that memory location. And since this is the location of the variable num the value also becomes 45. this shows how we can change the value of pointer directly using a pointer and the indirection pointer.

/* Program to display the contents of the variable their address using pointer variable*/

include< stdio.h >
{
int num, *intptr;
float x, *floptr;
char ch, *cptr;
num=123;
x=12.34;
ch=’a’;
intptr=&x;
cptr=&ch;
floptr=&x;
printf(“Num %d stored at address %u\n”,*intptr,intptr);
printf(“Value %f stored at address %u\n”,*floptr,floptr);
printf(“Character %c stored at address %u\n”,*cptr,cptr);
}

Pointer expressions & pointer arithmetic:

Like other variables pointer variables can be used in expressions. For example if p1 and p2 are properly declared and initialized pointers, then the following statements are valid.

y=*p1**p2;
sum=sum+*p1;
z= 5* - *p2/p1;
*p2= *p2 + 10;

C allows us to add integers to or subtract integers from pointers as well as to subtract one pointer from the other. We can also use short hand operators with the pointers p1+=; sum+=*p2; etc.,
we can also compare pointers by using relational operators the expressions such as p1 >p2 , p1==p2 and p1!=p2 are allowed.

/*Program to illustrate the pointer expression and pointer arithmetic*/
#include< stdio.h >
main()
{
int ptr1,ptr2;
int a,b,x,y,z;
a=30;b=6;
ptr1=&a;
ptr2=&b;
x=*ptr1+ *ptr2 –6;
y=6*- *ptr1/ *ptr2 +30;
printf(“\nAddress of a +%u”,ptr1);
printf(“\nAddress of b %u”,ptr2);
printf(“\na=%d, b=%d”,a,b);
printf(“\nx=%d,y=%d”,x,y);
ptr1=ptr1 + 70;
ptr2= ptr2;
printf(“\na=%d, b=%d”,a,b);
}

Format Specifiers in C


In this C programming language tutorial we take another look at the printf
function. We will look at how to use format specifiers to print formatted output
onto the screen. The topics covered are; a little printf background, format
specifiers and conversions, formatting of different types and format conversions
of strings.

printf Background

The printf function is not part of the C language, because there is no input or
output defined in C language itself. The printf function is just a useful
function from the standard library of functions that are accessible by C
programs. The behavior of printf is defined in the ANSI standard. If the
compiler that you’re using conforms to this standard then all the features and
properties should be available to you.

Format Specifiers

There are many format specifiers defined in C. Take a look at the following
list:

%i or %d

int

%c

char

%f

float

%lf

double

%s

string

Note:
 %lf stands for long
float.
Let’s take a look at an example of printf formatted output:

 #include<stdio.h>

 main()
 {
  int a,b;
  float c,d;

  a = 15;
  b = a / 2;
  printf("%d\n",b);
  printf("%3d\n",b);
  printf("%03d\n",b);

  c = 15.3;
  d = c / 3;
  printf("%3.2f\n",d);
 }

Output of the source above:

7
   7
007
5.10

As you can see in the first printf statement we print a decimal. In the second
printf statement we print the same decimal, but we use a width (%3d) to say that
we want three digits (positions) reserved for the output.

The result is that two “space characters” are placed before printing the
character. In the third printf statement we say almost the same as the previous
one. Print the output with a width of three digits, but fill the space with 0.
In the fourth printf statement we want to print a float. In this printf
statement we want to print three position before the decimal point (called
width) and two positions behind the decimal point (called precision).
The \n used in the printf statements is called an escape sequence. In this case
it represents a newline character. After printing something to the screen you
usually want to print something on the next line. If there is no \n then a next
printf command will print the string on the same line. Commonly used escape
sequences are:

  • \n (newline)

  • \t (tab)

  • \v (vertical tab)

  • \f (new page)

  • \b (backspace)

  • \r (carriage return)

  • \n (newline)
Let’s take another look at a printf formatted output in a more application like
example:

#include<stdio.h>

main()
{
 int Fahrenheit;

 for (Fahrenheit = 0; Fahrenheit <= 300; Fahrenheit = Fahrenheit + 20)
  printf("%3d %06.3f\n", Fahrenheit, (5.0/9.0)*(Fahrenheit-32));
}

Output of the source above:

  0 -17.778
 20 -6.667
 40 04.444
 60 15.556
 80 26.667
100 37.778
120 48.889
140 60.000
160 71.111
180 82.222
200 93.333
220 104.444
240 115.556
260 126.667
280 137.778
300 148.889

As you can see we print the Fahrenheit temperature with a width of 3 positions.
The Celsius temperature is printed with a width of 6 positions and a precision
of 3 positions after the decimal point. Let’s recap:

  • %d (print as a decimal integer)

  • %6d (print as a decimal integer with a width of at least 6 wide)

  • %f (print as a floating point)

  • %4f (print as a floating point with a width of at least 4 wide)

  • %.4f (print as a floating point with a precision of four characters after
    the decimal point)

  • %3.2f (print as a floating point at least 3 wide and a precision of 2)

Formatting other Types

Until now we only used integers and floats, but there are more types you can
use. Take a look at the following example:

 #include<stdio.h>

 main()
 {
  printf("The color: %s\n", "blue");
  printf("First number: %d\n", 12345);
  printf("Second number: %04d\n", 25);
  printf("Third number: %i\n", 1234);
  printf("Float number: %3.2f\n", 3.14159);
  printf("Hexadecimal: %x\n", 255);
  printf("Octal: %o\n", 255);
  printf("Unsigned value: %u\n", 150);
  printf("Just print the percentage sign %%\n", 10);
 }

Output of the source example:

The color: blue
First number: 12345
Second number: 0025
Third number: 1234
Float number: 3.14
Hexadecimal: ff
Octal: 377
Unsigned value: 150
Just print the percentage sign %


Note:
 In the last printf
statement only the percentage sign is printed.
The number 10 in this statement doesn’t matter; it’s not used in the output. So
if you want to print a percentage number you would use something like this:
printf(“%2d%%\n”, 10); (The output will be 10%)

Formatting Strings

By now you have seen most of the format conversion possible, but there is one
type that is a little different

and that are string format conversions. Take a look at the following example:

 #include<stdio.h>

 main()
 {
  printf(":%s:\n", "Hello, world!");
  printf(":%15s:\n", "Hello, world!");
  printf(":%.10s:\n", "Hello, world!");
  printf(":%-10s:\n", "Hello, world!");
  printf(":%-15s:\n", "Hello, world!");
  printf(":%.15s:\n", "Hello, world!");
  printf(":%15.10s:\n", "Hello, world!");
  printf(":%-15.10s:\n", "Hello, world!");
 }

The output of the example above:

:Hello, world!:
:  Hello, world!:
:Hello, wor:
:Hello, world!:
:Hello, world!  :
:Hello, world!:
:     Hello, wor:
:Hello, wor     :

As you can see, the string format conversion reacts very different from number
format conversions.

  • The printf(“:%s:\n”, “Hello, world!”); statement prints the string (nothing
    special happens.)

  • The printf(“:%15s:\n”, “Hello, world!”); statement prints the string, but
    print 15 characters. If the string is smaller the “empty” positions will be
    filled with “whitespace.”

  • The printf(“:%.10s:\n”, “Hello, world!”); statement prints the string, but
    print only 10 characters of the string.

  • The printf(“:%-10s:\n”, “Hello, world!”); statement prints the string, but
    prints at least 10 characters. If the string is smaller “whitespace” is
    added at the end. (See next example.)

  • The printf(“:%-15s:\n”, “Hello, world!”); statement prints the string, but
    prints at least 15 characters. The string in this case is shorter than the
    defined 15 character, thus “whitespace” is added at the end (defined by the
    minus sign.)

  • The printf(“:%.15s:\n”, “Hello, world!”); statement prints the string, but
    print only 15 characters of the string. In this case the string is shorter
    than 15, thus the whole string is printed.

  • The printf(“:%15.10s:\n”, “Hello, world!”); statement prints the string, but
    print 15 characters.

    If the string is smaller the “empty” positions will be filled with “whitespace.”
    But it will only print a maximum of 10 characters, thus only part of new
    string (old string plus the whitespace positions) is printed.

  • The printf(“:%-15.10s:\n”, “Hello, world!”); statement prints the string,
    but it does the exact same thing as the previous statement, accept the
    “whitespace” is added at the end.

A little warning!


The printf function uses its first argument to determine how many arguments will
follow and of what types they are. If you don’t use enough arguments or if they
are of the wrong type than printf will get confuses, with as a result wrong
answers.
That’s all for this C tutorial. Just make some examples of your own, they are
easy to make. This is the only way to learn and see how the format conversions
reacts.