Pages

Friday, November 26, 2010

Pointers and constants

If you remember the "const" keyword before a variable name implies that the variable is a constant and can not be modified during the runtime. This saves us from accidental manipulation of a value. For example days of the week are 7 and will remain like this in centuries to come. If we declare the variable days as "int days", a statement like "days++" can accidently increment to an invalid value. Therefore, we should declare the variable as "int const days=7", this will make the variable as constant. If a statment is written to change the value, the compiler will show an error specifiying that the variable can not be modified since it is a constant.
Similarly if a pointer is declared as a constant, we can not change it to point to any other value. This means a constant pointer always points to a fixed value. Let's see how it works

    int x=10;
    int *ptr=&x;   
    int * const cptr=&x;
    ++ *ptr; // Valid , increments the value at ptr
    ++ *cptr; // Valid, increments the value at cptr
    ++ cptr;// Invalid, since cptr is a constant pointer and can not be modified.

   
In the above code, x is an integer variable with a value of 10. ptr is a pointer to x so is cptr. The difference between the two pointers is that ptr can be modified to point to any other integer while cptr is a constant pointer. When the statement "++cptr" is encountered the compiler will return an error stating that the pointer can not be modified.

Pointer to a constant

A pointer which points to a constant is called "Pointer to a constant". Using a "pointer to a constant", the constant value can not be modified but the pointer can be made to point to another location. Consider the following code :
    const int days=7; // a constant integer variable
    const int *ptr=&days; // a pointer to a constant
    ++ *ptr; // Invalid, since the statement will try to increment the value of days which is a constant
    ++ ptr; // Valid. Since the pointer is not a constant. The value to which it is pointing is.

   
This is a simple declaration of the variable myPtr. myPtr is a pointer to a character variable and in this case points to the character 'A'. Don't be confused about the fact that a character pointer is being used to point to a single character—this is perfectly legal! Not every character pointer has to point to a string.

Now consider the following three declarations assuming that char_A has been defined as a type char variable.:

const char * myPtr = &char_A;
char * const myPtr = &char_A;
const char * const myPtr = &char_A;


They are all three valid and correct declarations. Each assigns the addres of char_A to a character pointer. The difference is in what is constant.

The first declaration:

const char * myPtr

declares a pointer to a constant character. You cannot use this pointer to change the value being pointed to:

char char_A = 'A';
const char * myPtr = &char_A;
*myPtr = 'J';    // error - can't change value of *myPtr

The second declaration,

char * const myPtr

declares a constant pointer to a character. The location stored in the pointer cannot change. You cannot change where this pointer points:

char char_A = 'A';
char char_B = 'B';

char * const myPtr = &char_A;
myPtr = &char_B;    // error - can't change address of myPtr

The third declares a pointer to a character where both the pointer value and the value being pointed at will not change.

Thursday, November 25, 2010

Advanced Strings

Let's make some more programs using character pointers.Don't forget that strings are arrays of characters. Read the description at the end to understand the code.

Example 1 - To copy a string to another

#include
#include
void main()
{
    clrscr();
    void copy(char *);
    char str1[10],str2[10];
    printf("\nEnter a string  : ");
    scanf("%s",&str1);
    copy(str1);
}
void copy(char *s)
{
    int i=0;                     // Line  1
    char str2[10];         // Line 2
    while(*s!='\0')         // Line 3
    {                               // Line 4
        str2[i++]=*s;     // Line 5
        s++;                   // Line 6
    }                           // Line 7
    str2[i]='\0';         // Line 8   
    printf("\nStr2 %s",str2);    // Line 9
}


Description

We ask the user to enter a string and place it in the string "str1". While calling the function "copy", we passed the value of "str1" to the argument "s". Inside the function we have another string2 which we will use as the target string. Let's see how the source("str1") is copied to the target("str2"). In the example we are assume that the user has entered the word "hello".


Line 1-> str1="hello"  is copied to the argument "s" in the function copy()
Line 2 -> str2=NULL
Line 3 -> *s="h" (s points to the first character of hello)
since *s is not equal to '\0, the compiler enters the loop.
Line 5 -> The first index of str2 which is 0 is assigned the value at "s" which is "h".
Line 6 -> The value of "s" is incremented so that it now points to the next char which is "e".
The loop continues till the value at "s" is not equal to '\0', which is the end of the string.
Line 8 -> After all the characters have been copied to to "str2", the null character "\0" is appended  to the end of the string. This will make "str2" a string which terminates with "\0"
Line 9 -> Once the string is copied,it is printed.
                       
Since parameters are passed by value, in both the passing of a character pointer or the name of the array as above, what actually gets passed is the address of the first element of each array. Thus, the numerical value of the parameter passed is the same whether we use a character pointer or an array name as a parameter. 
Another way to traverse the string would be to change:
while (*source != '\0')
to simply
while (*source)
since the value within the parenthesis will go to zero (FALSE) at the same time in either
case.

Example 2  - To find out the length of a string without using the strlen()

#include
#include
void main()
{
    clrscr();
    int len=0;
    char *text;
    printf("\nEnter a sentence  : ");
    gets(text);
    while(*text!='\0')
    {
        len++;
        text++;
    }

    printf("\nLength of the string is %d",len);
}


Description
The above program is very simple. It prompts the user to enter a sentence. Note that the function to get the string from the user is "gets()" and not "scanf()". This is because we want to allow the user to enter spaces in between the string. You can replace the "gets()" with "scanf()" if required.  To find the length of the string, we are running a loop which runs till the end of the string.On each run of the loop the value of "len" is incremented by 1. When the loop closes, the value of length will be printed.

Wednesday, November 24, 2010

Pointers and strings

Strings in C and C++ are defined as "collection of characters terminated by a null character". All the strings must end with the null character("\0") which marks the end of the string. For example:
char text[20];
text[0] = 'H';
text[1] = 'e';
text[2] = 'l':
text[3] = 'l';
text[4] = 'o';
text[5] = '\0';

As you can see the word "hello" has "\0" added to its end. This method of assigning values to individual character is OK for small strings, but for a large string this method is be very time consuming, therefore
we use the following 2 alternate methods.

In the first method  we can write -
char text[20] = {'H', 'e', 'l',  'l', 'o','\0'};

whereas the second method is pretty easy in which we can write like
 char text[20] = "Hello";

Note that the previous examples were using single quotes but the last example is using double quotes. Also we are not appending the null character '\0' ourselves it will be automatically added to the end of  the string "Hello".

No matter which method you choose the compiler will allocate 20 bytes to store the string. Remember that for a string the allocated memory is always contiguous. After the allocation the first 6 bytes are initialized to "Hello\0".

A char can also be pointed to by a char pointer. For this, the pointer has to be declared using the "char" type.

    char c='A';
    char *cp=&a;
    printf("\nC is %c",c); // prints A
    printf("\n*CP is %c",*cp); // prints A


As you can see the pointer(cp) is pointing towards c which contains a value 'A', when printed using the "value at" operator(*) it prints the value of C which is 'A'. Similarly, we can assign the address of a string to a pointer. For example the following code prints a string in a vertical manner.

    char str[]="This is fun";
    for(int i=0;str[i]!='\0';i++) // runs the loop till the end of string is reached.
        printf("\n%c",str[i]);


The same program can be written using a pointer as evident from the following code.
    char str[]="This is fun";
    char *cptr; // A pointer which can point to a char
    for(cptr=str;*cptr!='\0';cptr++)
        printf("\n%c",*cptr);


Before understanding the above code I would like to remind you that an array is actually a pointer pointing to the first element of the collection. This means that it seems that str has the value "This is fun", but actually it is pointing only to  the address of "T" which is the first character of the collection. Assuming that the address of "T" is "100", Here is the internal structure of the string "str" with "This is fun" stored inside it.

Character                    Assumed Address
T                       ->      100
h                       ->       101
i                        ->       102
s                       ->       103
(space)             ->       104
i                        ->       105
s                       ->       106
(space)             ->       107
f                       ->       108
u                      ->       109
n                      ->       110
\0                     ->       111

Inside the loop when we use the statement "cptr=str", we are assigning the value of str(which is 100) to cptr. Therefore both "str" and "cptr" are pointing to the address of "T".  The second part of the loop says that we want to run the loop body till the value at "*cptr" is not equal to the null character. When the loop runs for the first time the value of cptr is 100, but the value at cptr(*cptr) is "T" which definitly is not equal to the null character. Since the condition is true the compiler enters the loop body where the value at "cptr" ("T")is printed. The loop runs again and the value of cptr is incremented by 1(cptr++) . Since it was "100" before it becomes 101 now where the alphabet "h" is stored. "h" is printed and the value is increment again to 102. In this way, the loop reaches to the end of the string where "n" is stored. It advances to the address 111 where the "\0" character is placed. The loop condition becomes false and the loop terminates but only after printing all the characters of the string one by one vertically.

Monday, November 22, 2010

Pointers and structures

Structures are user defined datatypes(refer to earlier posts for a detailed study). We can not only create pointers for variables which have an inbuilt data type but also for variables which have a structure  datatype. The declaration of such a pointer is same as of a normal pointer as evident from the declaration below

struct computer
{
    char processor[12];
    char make[10];
    short ram;
}com,*comp;



In the above code we have declared a structure name "computer" which has three member variables namely processor,make and ram. What these variables are for is not relevant for this topic. What is important is that we have declared 2 objects - com and *comp of the structure. The first object(com) is a simple object which can access the member variables of the structure using the dot (.) operator like - com.processor, com.make etc. but the second object is a pointer object. Just like an integer pointer can point to any integer, a structure pointer can point to any thing which is of structure type. In other words "*comp" can point to any variable/object which has "computer" as its datatype. You can see processor is of char type, so is make and ram is of int type. There is only one variable which has its datatype as "computer" and it is "com". So the pointer "*comp" can point to "com".

How it is done

Let's go through the complete code to see how it is done.


Example 1

struct computer
{
    char processor[12];
    char make[10];
    short ram;
}com,*comp;


void main()
{
    // Populating the com object of the structure computer using the "." operator
    printf("\nEnter Processor Type  ");
    scanf("%s",&com.processor);
    printf("\nEnter Company name ");
    scanf("%s",&com.make);
    printf("\nEnter Amount of Physical RAM (In GB) ");
    scanf("%d",&com.ram);

    comp=&com; // making comp point to com

    //Printing the data using the object
    printf("\nProcessor %s",com.processor);
    printf("\nCompany Name %s",com.make);
    printf("\nRAM In GB %d",com.ram);

    //Printing the data using the pointer
    printf("\nProcessor %s",comp->processor);
    printf("\nCompany Name %s",comp->make);
    printf("\nRAM In GB %d",comp->ram);

}

Description
The program has a structure named "computer" with three variable as members - processor,make and ram. The two object "com" and "*comp" are declared just after closing the structure declaration making them public for all the functions of the program. The "com" object is initialised by asking the values from the user and storing them in the object by using the "." operator. The pointer object (comp) comes into play only when the statement "comp=&com" is reached. This statement makes the pointer(comp) point to the object (com). Now that it is a pointer to the object it can access the values of the object. To access the value of the object the arrow operator(->) is used. It is made by pressing the hyphen or the minus("-") sign with the greater than(>) sign. Just as a normal object access the values of the structure using a dot operator, a pointer object accesses the values using the arrow operator.


Example 2

Using a structure pointer with a function

#include
#include
struct worker
{
    int work_code; // worker code
    char work_name[12];// name of the worker
    int work_sal;//salary of the worker
}work1,work2,*work_ptr;

void main()
{

    clrscr();
    void show_worker(worker *);
    printf("\nEnter First Worker's Data ");
    printf("\nEnter Code of The Worker ");
    scanf("%d",&work1.work_code);
    printf("\nEnter Name of The Worker ");
    scanf("%s",&work1.work_name);
    printf("\nEnter Salary of The Worker ");
    scanf("%d",&work1.work_sal);

    work_ptr=&work1;
    show_worker(work_ptr); //calling the function with the firstobject

    printf("\nEnter Second Worker's Data ");
    printf("\nEnter Code of The Worker ");
    scanf("%d",&work2.work_code);
    printf("\nEnter Name of The Worker ");
    scanf("%s",&work2.work_name);
    printf("\nEnter Salary of The Worker ");
    scanf("%d",&work2.work_sal);
    work_ptr=&work2;
    show_worker(work_ptr);//calling the function with the secondobject
}
void show_worker(worker *wptr)
{
    printf("\nWorker code : %d",wptr->work_code);
    printf("\nWorker name : %s",wptr->work_name);
    printf("\nWorker salary : %d",wptr->work_sal);
}

Description

The "worker" structure has 2 normal objects (work1 and work2) and a pointer object (work_ptr) which points to both the objects one by one. It first points to the first object (work1) in the statement - work_ptr=&work1. Once work_ptr has the address of work1 it is passed as an argument to the function (show_worker) which takes one argument of "worker *". The value of work_ptr is "copied" to "wptr" which is declared in the argument list of the function. At this point it can be said that since "work_ptr" has been copied to "wptr", both these pointers are now pointing to "work".  When the function is first called it prints the code,name and salary of the first worker since the pointer has the address of the first object. Similarly before the second call is made the pointer is pointed towards the second object in the statement "work_ptr=&work2". In the second call the value of work_ptr is again copied to wptr which this time prints the data of the second object.


Sunday, November 21, 2010

Pointer and Arrays

Pointers are arrays are closely related with each other. The relationship between an array and a pointer is in fact so close that it can be said that "an array is actually a pointer, pointing to the first element in the collection." Till this time we have learnt that an array is a collection of variable of same datatype, therefore to know that array is actually a pointer you can find hard to digest. Before going on its details let's discuss some other topics first.

Array of pointers
If you have just 1 or 2 variables to point you can easily declare equal number of variable to point them, what if you have say 20 to 30 variable to point ? Will you declare so many variables, what if the variables are even more ? It would be impractical to say that one will declare 50 pointers or 100 pointers, so how will we create so many pointers? The answer is simple - Array of pointers. Just as an array of variable can store multiple variables, an array of pointers can store multiple pointers. This will not only save us from the trouble of declaring so many pointers but will also make the program very short. Let's see how it is done

Example 1
#include
#include
void main()
{
    int a=1,b=2,c=3,d=4,e=5;
    int *ptr[5];
    p[0]=&a; //storing the address of a in p[0]
    p[1]=&b;
    p[2]=&c;
    p[3]=&d;
    p[4]=&e;
    // printing all the variables
    printf("\nA %d",a); // 1
    printf("\nB %d",b); // 2
    printf("\nC %d",c); // 3
    printf("\nD %d",d); // 4
    printf("\nE %d",e); // 5
    // printing their address using the pointer array
    printf("\nP[0] %d",p[0]);   // address of a
    printf("\nP[1] %d",p[1]);  // address of b
    printf("\nP[2] %d",p[2]);  // address of c
    printf("\nP[3] %d",p[3]);  // address of d
    printf("\nP[4] %d",p[4]);  // address of e
    //printing the values of the variables through the array
    printf("\nP[0] %d",*p[0]);   // value of a
    printf("\nP[1] %d",*p[1]);  // value of b
    printf("\nP[2] %d",*p[2]);  // value of c
    printf("\nP[3] %d",*p[3]);  // value of d
    printf("\nP[4] %d",*p[4]);  // value of e
   
}


Description
In the code given above, we have 5 different variables. To point these variables we need 5 different pointers. Instead of declaring 5 pointers, we declare an array of 5 pointers named "p". Now to store the address of the first variable "a" in index 0 of array p, we use a statment - "p[0]=&a". This will put the address of "a" in the first element of our array pointer. Similarly the addresses of rest of the variables (b,c,d,e) are stored in index 1,2,3,4 respectively. Once the array has all the required address we can easily print all the address or the values by using simple "printf()" statments.


Example 2  - Same program using loop
#include
#include
void main()
{
    int a=1,b=2,c=3,d=4,e=5,i;
    int *ptr[5];
    p[0]=&a; //storing the address of a in p[0]
    p[1]=&b;
    p[2]=&c;
    p[3]=&d;
    p[4]=&e;
    // printing all the variables
    printf("\nA %d",a); // 1
    printf("\nB %d",b); // 2
    printf("\nC %d",c); // 3
    printf("\nD %d",d); // 4
    printf("\nE %d",e); // 5
    // printing their address using the pointer array
    for(i=0;i<5;i++)
        printf("\nP[i] %d",p[i]);
   
    //printing the values of the variables through the array
    for(i=0;i<5;i++)
        printf("\nP[0] %d",*p[i]);   // value of a
       
}

Description
This is the same program but it uses a loop to print the address as well as the values. This will make the program quite small specially if the array is too large. The first loop prints the addresses whereas the second one is used to print values.

Friday, November 19, 2010

Declaring a pointer

Pointers :
When instead of a value, we are interested in the address of a variable, we can create a special variable which is capable of doing this task. Such a variable is called "Pointer". It can point to any memory location of the computer's RAM. This feature makes them not only powerful but also very dangerous. If not handled properly pointers can point to any location and cause serious damage to the system. Virus programmer world over use them for creating harmful viruses.
Declaring a pointer is similar to declaring a variable with just one difference, that is the pointer name is prefixed with an "*" mark. The "*" tells the C compiler that we want to declare a pointer variable, i.e., to set aside however many bytes are required to store an address in the memory.
        int *ptr;
here, "int" is the datatype of the variable of which we want to store the address. Which means if we want to store the address of a float we will declare the pointer as
        float *myptr;
In both the above examples, ptr and myptr are just variable names and can be replaced by any other legal variable name.

Intialising the pointer
Once the pointer has been declared it must be assigned a value which it can manage. Just as an integer variable can store numerical values, a pointer can store address of other variables. It is a good practice to initialise a pointer as soon as it is declared or else  it can point to any random address in the memory causing the system to crash. If we don't have a variable to make the pointer to we should the use the macro "NULL" to make the pointer a null pointer. A null pointer is the one which is not currently pointing to a legal variable. If there is a variable to which it can point then the unary operator "&" (Address of) can be used to make the pointer point to something.
        int x=10; --> line 1
        int *ptr; --> line 2
        ptr=&x; --> line 3
The first line simply declares a variable named "x" with a value of 10. The second line declares a pointer named "ptr". Note that the name is prefixed with an "*" symbol. The third line assigns the address of x to ptr. To initialise a pointer we will use the "&" operator which will assign the address of x to the pointer "ptr". What will the address x? Nobody knows it for sure,since it is not in our hands to assign the address to a variable we can just assume an imaginary address, say "1024". Therefore if x's value is 10, ptr's value is the address of "x" which we are assuming as "1024". Now if we print the value of both "x" and "ptr" using the following statements,
        printf("\nThe value of x is %d",x);
        printf("\nThe value of ptr is %d",ptr);

You will see that the first statement will print "10" since it is the value of "x", but the second statement will print "1024" since this is the value it is holding. If you don't see "1024" on screen as ptr's value but -12 or -14 don't lose heart since it the integer representation of the memory address. Moreover "1024" is just the assumed address which will vary from system to system.   

With a pointer we can not only print the address of the variable but also its value. To print the value of a variable through a pointer we will have to use what we call as the "dereferencing operator" which  is an asterisk and it is used as follows:

        printf("\nThe value of x, printed through the pointer is %d",*ptr);

Note the use of "*" while printing the value. This will print the value the value of the variable of which ptr is a pointer. In our example, ptr is a pointer of x, therefore the value printed will be 10.

Similarly, if we write a statement like the following
        *ptr = 123;
will copy 123 to the address pointed to by ptr. Thus if ptr "points to" (contains the address
of) x, the above statement will set the value of x to 123. That is, when we use the '*' this
way we are referring to the value of that which ptr is pointing to, not the value of the
pointer itself.

Example 1

#include
#include

void main()
{
    int x;
    int *xptr;
    x=100;
    xptr=&x; // initialising the pointer by assigning it the add. of x
    printf("\nValue of x is %d",x);
    printf("\nAddress of x is %d",xptr); // will print the add. of x
    printf("\nValue of x through the pointer is %d",*xptr);//will print the value of x
}


Example 2

#include
#include
void main()
{
    int x, y;
    int *xptr,*yptr;
    x=100;
    y=200
    xptr=&x;
    yptr=&y;
    printf("\nValue of x is %d",x); // will print 100
    printf("\nAddress of x is %d",xptr); will print the address of a
    printf("\nValue of x through the pointer is %d",*xptr); // will print 100
    printf("\nValue of y is %d",y);  // will print 200
    printf("\nAddress of y is %d",yptr); will print the address of y
    printf("\nValue of y through the pointer is %d",*yptr); // will print 200
    xptr=yptr; // making xptr point to what yptr is pointing to. This will make  both pointers                 // pointing towards y

    printf("\nValue of x is %d",x); // will print 100
    printf("\nAddress of x is %d",xptr);  // will print the address of y since the pointer has been                     //modified
    printf("\nValue of x through the pointer is %d",*xptr);// will print 200

     }


Description
In the above program we have declared 2 variables namely x and y, and 2 pointer xptr and yptr which
point to x and y respectively. When the value are printed, x prints 100,xptr prints its value which is the address of x, and *xptr prints the value of x. Similarly y prints 200, yptr prints address of y and *yptr prints the value of y. The statement "xptr=yptr" assigns the value of yptr(that is address of y) to xptr. This means that now both the pointers are pointing to y . Now that xptr is pointing to y , printing its details again will print the same values which yptr was printing since they are both pointers of y . The value of a will still be 100 since it has not been modified.


Example 3
#include
#include
void main()
{
    int x=5,*xptr
    xptr=&x;

    printf("\nx = %d",x);// 5
    printf("\nxptr = %d",xptr);// address of x
    printf("\nValue at ptr = %d",*xptr);// 5
   
    x++; // First increment
   
    printf("\nAfter incrementing the value of x by 1 ");
   
    printf("\nx = %d",x);// 6
    printf("\nxptr = %d",xptr);// address of x  , same as before
    printf("\nValue at xptr = %d",*xptr);// 6

    *xptr++;  // Second increment
   
    printf("\nAfter incrementing the value at xptr by 1 ");
   
    printf("\nx= %d",x);// 7
    printf("\nxptr = %d",xptr);// address of a  , same as before
    printf("\nValue at xptr = %d",*xptr);// 7
   
    xptr++;  // Third increment
   
    printf("\nAfter incrementing the value of xptr by 1 ");
   
    printf("\nx = %d",x);// 7
    printf("\nxptr = %d",xptr);// a new address
    printf("\nValue at ptr = %d",*xptr);// a new value (garbage)

}

Pointers

What is a pointer
You must have seen sign boards, arrows pointing towards a shop, mall or office. Such signs help the visitors in reaching the place correctly. All such boards or signs which are used to "point" to any building are actually "pointers" to something like office or shop. The same task is performed by C pointers by "pointing" to the location of a variable in memory. A pointer technically is a variable which points to or stores the address of another variable in the memory or RAM. The difference between a pointer variable and a normal variable is that a normal variable stores "normal" values like someone's name, address,telephone number or any other value which the user wants it to store, a pointer on the other hand does not store such values instead it stores memory address of any variable in the memory.

Why is it needed
You must be aware of the fact that the RAM is divided into rows and columns where each intersection (i.e., cell) is a memory block where data is stored. When we declare a variable say "int x", the compiler first reads the data type (which is 'int' in this case) and then sets aside a particular amount of memory required to store this variable in memory. For example, when it sees that the variable is of "int" type, it allocates 2 bytes of memory for the data that we will stored and labeled as "x".  The compiler does not internally refers to the memory locations as a, b , c, etc. instead the addresses are in hexadecimal form.
These hexadecimal addresses are difficult to remember and moreover, are not known previously to anybody, therefore to make their calling easy we are provided with the facility of naming them using friendly names like marks,salary,data etc., which are the variable names. So to say that what we refer to it as price,days,income etc. are the easy names of complex memory addresses. Coming back to memory addresses each variable is assigned a unique memory address allocated by the OS. For example, if there is a declaration such as :

        int marks;

the compiler will label a memory block with the name "marks". When we initialise a value in the
this variable, using a statement like
        marks = 80;
There are actually two "values" associated with the variable marks. One is the value of the
integer stored there (2 in the above example) and the other the "value" of the memory
location, i.e., the address of marks. The two values are also called
rvalue (right value) and lvalue (left value) respectively. Don't forget that in C, the assignment is always made to the variable on the left side of the assignment operator (=).