The greatest mistake you can make in life is to be continually fearing you will make one

Wednesday 17 March 2010

C Question of the Day -malloc(),calloc(),realloc(),free()

1. Will this result in any runtime error?
#include <stdlib.h>
main()
{
int p;
p=calloc(1,sizeof(int));
free(p);
p=NULL;
free(p);
}   
Solution

No
Freeing a null pointer wont result in any error; The free() call would return without doing anything


2. Will this result in any runtime error?
#include <stdlib.h>
main()
{
int *p;
p=calloc(1,sizeof(int));
free(p);
p=realloc(p,sizeof(int));
}
Solution

Yes Error: "glibc detected ** ... : double free or corruption"
Reason: "realloc(ptr,size)" has to be invoked after (m|c)alloc(), but before free()


3. Will this result in any runtime error?

#include <stdlib.h>
main()
{
int p;
p=calloc(1,sizeof(int));
free(p);
p=NULL;
p=realloc(p,sizeof(int));
}
Solution

No
"realloc(,size)" is equivalent to "malloc(size)"

4. Will this result in any runtime error?

#include <stdlib.h>
main()
{
int *p;
p=calloc(1,sizeof(int));
free(p);
p=realloc(p, 0 * sizeof(int));
p=NULL;
p=realloc(p, 1 * sizeof(int));
*p=1;
free(p);
}
Solution

Yes. Error: "glibc detected ** ... : double free or corruption"
Reason: realloc(,0) is equivalent to free(); So we end up with double free


5.What is the output of the following program?
#include<stdio.h>
void main()
{
    int *mp,*cp;
    mp=(int*)malloc(sizeof(int));
    printf("mp=%d\n",*mp);
    cp=(int*)calloc(sizeof(int),1);
    printf("cp=%d\n",*cp);
}
Solution

mp=garbage value
cp=0
The memory space allocated by malloc is uninitialized, so mp has some garbage value. calloc initilize the allocated memory space to zero. so cp=0


6.What is the output of the following program?
#include<stdio.h>
void main()
{
    char *pd,*ps="I LOVE C";
    pd=malloc(strlen(ps));
    strcpy(pd,ps);
    printf("%s",pd);
    free(pd);
}
  1. free() fails
  2. strcpy() fails
  3. prints I LOVE C
  4. error
Solution

3.prints I LOVE C


7.What is the output of the following program?
#include<stdio.h>
void main()
{
    int *p;
    p=(int *)malloc(-10);
    printf("p=%d",*p);
    free(p);
}
Solution

Segmentation Fault


8.What is the output of the following program?
#include<stdio.h>
int main()
{
    int *p;
    p=(char *)malloc(sizeof(10));
    printf("The starting address is %d\n",p);
    return 0;
}
  1. Compilation Error
  2. Runtime Error
  3. Will give a warning,but run anyway
  4. neither warning nor error
Solution

3.Will give a warning,but run anyway
The starting address is 14311440

Common Problems with malloc() and calloc() functions in C

1) Forgetting to initialize the allocated memory (malloc only)
Example:
int p=malloc((sizeof (int))*5);
p[0]++;

Solution:
The memory allocated using malloc() function contains garbage values.Initialize malloc-ed memory using memset
int *p=malloc((sizeof (int))*5);
memset(p,0, (sizeof (int))*5);
p[0]++;

2) Using more memory than allocated memory
Example:
int *p=calloc((sizeof (int)),5);
p[5]++;

3. Forgetting to allocate memory for storing the null character when using strings
Example
char *p=calloc((sizeof (char)),5);
strcpy(p,"NULL?");

Solution:
char *p=calloc((sizeof (char)),6);
strcpy(p,"NULL?");

4. Referring de-allocated memory (free-d memory)
Example:
int *p=calloc((sizeof (int)),5);
for (i=0;i < 5;i++)
     p[i]=i;
free(p);
...
...
*p=1;

Solution:
The line "*p=1;" could trigger a "Segmentation fault" error during run-time. But not guarenteed always.
This can be hard to trouble-shoot; So it is always a good idea to re-initialize the pointer to NULL after freeing

int *p=calloc((sizeof (int)),5);
for (i=0;i<5;i++) p[i]=i;
free(p);
p=NULL;
...
...
*p=1; == > This always triggers a "Segmentation fault" error during run-time

5. Double free-ing for memory
int *p1,*p2;
p1=calloc((sizeof (int)),5);
p2=p1;
free(p1);
p1=NULL;
...
...
...
*p2=0; // Can result in "Segmentation fault";
free(p2); // Would trigget the runtime error "glibc detected ** ... : double free or corruption"

Both p1 and p2 were pointing to the same memory and called free for that memory
However p2 still points to the memory.

Soln: Remember to re-initialize the copied pointers also to NULL
int p1,*p2;
p1=calloc((sizeof (int)),5);
p2=p1;
free(p1);
p1=NULL;
p2=NULL;
...
...
...
*p2=0; // Will always result in "Segmentation fault";
free(p2); // Will always result in "Segmentation fault";

Hint: Whenever you see the error "Segmentation fault" or "glibc detected ** ... : double free or corruption" error in a "free" call, check if you have already called a free for the same memory

6. Freeing unallocated memory
Example:
The following works fine
#define NEED_MEM 1
int *p;
if (NEED_MEM) {
p=calloc((sizeof (int)),5);
}
...
...
free(p);

But the following doesn't
#define NEED_MEM 0
int *p;
if (NEED_MEM) {
p=calloc((sizeof (int)),5);
}
...
...
free(p); // May result in "Segmentation fault"

Solution:
Always initalize pointers to NULL
#define NEED_MEM 0
int *p=NULL;
if (NEED_MEM) {
p=calloc((sizeof (int)),5);
}
...
...
free(p); // No problem here... [Remember that there is nothing wrong in freeing NULL memory; free call would return without doing anything]

Tuesday 16 March 2010

Memory Management in C

  • A memory is made up of large number of cells,where each cell is capable of storing one bit.
  • The cells may be organized as a set of addressable words,each word storing a sequence of bits
  • These addressable memory cells should be managed effectively to increase its utilization.This is called memory Management.
  • There are 2 types of memory allocations in C

    1. Static memory allocation or Compile time allocation
    2. Dynamic memory allocation or Run time allocation
1.Static or compile time memory allocation
  • The required memory is allocated to the variables at the beginning of the program.
  • The memory to be allocated is fixed and is determined by the compiler at the compile time itself.
  • Example:
        int a,b;
        float x,y[5];
    when the first statement int a,b; is compiled 4 bytes(integer occupies 4 bytes in a 32 bit machine) for each variable a,b will be allocated. The statement float x,y[5]; will allocate 4 bytes for the x variable and 20 bytes[5 element array, each has 4 bytes] for the array y.
Drawbacks:
  • If we declare more number of elements and we are using less number of elements then the memory allocated for the not used variables will be wasted.The unused memory cells are not made available to other applications.This leads to inefficient use of memory.
    Example
    main()
    {
        int x,y[10];
        x=10;
        printf("%d",x);
    }
    Here y[10] array is declared but not used in the program.So the memory allocated for the array is wasted.
  • If we try to assign values to 10 elements of an array whose size is declared as 5,then first 5 elements can be assigned and the other 5 elements cannot be assigned.
  • If we try to read 10 elements of an array whose size is declared as 5,then first 5 values are read from the array and the other 5 consequtive unknown random memory values will be read.
2.Dynamic or Runtime memory allocation
  • In most of the real time problems, we cannot predict the memory requirements.
  • It makes efficient use of memory by allocating the required amount of memory whenever is needed.
  • dynamic memory allocation does the job at run time.
  • C provides the following dynamic allocation and deallocation functions

    1. malloc()
    2. calloc()
    3. realloc()
    4. free()
    The allocation of memory is done using 3 functions malloc,calloc and realloc. deallocation is done by free function.
1.Allocating A Block of Memory-malloc()
  • The malloc() function is used to allocate a block of memory in bytes dynamically during execution.
  • This function requires the number of bytes to be allocated and returs the base address of the chunk of memory that it allocates.
  • The address returned by malloc() is always of the type void*.Hence it is required to convert in to a required data type using typecastng.
  • Syntax:
        ptr=(data-type *)malloc(block_size);
  • Example:Allocating memory space for n integers of int type
       p=(int *)malloc(n*sizeof(int));
  • The malloc() function allocates a block of contiguous bytes.The allocation can fail if the space in the heap is not sufficient to satisfy the request. If it fails,it returns a NULL pointer.So it is always better to check whether the memory allocation is successful or not before using the allocated memory.
    Example
              
    #include<stdio.h>
    int main()
    {
        int n,i,sum=0;
        int *p,*num;
        printf("Enter the number of elemets\n");
        scanf("%d",&n);
        //allocating memory space for n integers
        p=(int *)malloc(n*sizeof(int));
        //Checking whether the memory is allocated successfully or not
        if(p==NULL)
        {
            printf("Memory allocation is failed\n");
            exit(0);
        }
        //Reading the elements
        for(num=p,i=1;num<(p+n);num++,i++)
        {
            printf("\nEnter the %d element=",i);
            scanf("%d",num);
        }
        //Finding the sum of n elements
        for(num=p;num<(p+n);num++)
        {
            sum=sum+(*num);
        }
        printf(\nSum=%d",sum);
        return 0;
    }
    Output
    Enter the number of elemets
    5
    Enter the 1 element=4
    Enter the 2 element=5
    Enter the 3 element=6
    Enter the 4 element=7
    Enter the 5 element=8
    Sum=30
2.Allocating Multiple blocks of Memory-calloc()
  • calloc functionworks similar to malloc() function except it needs 2 arguments and calloc() function allocates multiple blocks of memory each of the same size and then sets all bytes to zero.
  • Syntax:
        ptr=(data-type *)calloc(n,sizeof(block_size));
    This will allocates contiguous space for 'n' blocks,each of size of block_size bytes.All bytes are initialized to zero and a pointer to the first byte of the allocated memory block is returned.
  • Example
        p=(int *)calloc(25,sizeof(int));
  • calloc(m,n) is equivalent to p=m*malloc(n);
Differnce between malloc() and calloc()
  1. malloc() allocates a bytes of memory but calloc() allocates blocks of memory.
  2. malloc() takes a single argument(memory required in bytes) but calloc() takes 2 arguments (number of variables to allocate memory,size in bytes of a single variable)
  3. The memory allocated using malloc() function contains garbage values,the memory allocated by calloc() function contains the value 0.
3.Resize the size of a Memory-realloc()
  • Sometimes we need to increase the memory space or we want to reduce the memory space.
  • To change the size of the allocated memory block realloc() function is used.
  • Syntax
        ptr=realloc(ptr,new_size);
    ptr- >pointer holding the starting address of the allocated memory block
    new_size=size in bytes
  • Example
        ptr=(int *)malloc(sizeof(int));
        ptr=(int *)realloc(ptr,sizeof(int));
4.Releasing the used memory-free()
  • free() function is used to deallocate the previously allocated memory using malloc() or calloc() function.
  • It is important to release the memory block for future use when it is not in use,using free() function.
  • Syntax
        free(ptr);
    ptr is a pointer to a memory block which has already been allocated.
  • Trying to release an invalid pointer may create problems and cause system crash.

Sunday 14 March 2010

Problems based on Binary Tree

1.A strictly binary tree contains 10 leaves(nodes dont have children). find the total number of nodes in the tree?

Solution

Total number of nodes=19
A strictly binary tree with n leaves always contains 2n-1 nodes.so the tree has 2*10-1 ie 19 nodes

2.A binary tree has 20 nodes. Then how many null branches have the tree?

Solution
Answer=21 null branches
If the tree has 3 nodes then it has 4 null branches.ie 3+1. If the tree has 5 nodes then it has 6 null branches.ie5+1. In general a binary tree with n nodes has exactly n+1 null nodes. So 20 nodes has 21 null branches.



3.In the given binary tree below, in which location the node 4 is stored in an array?
Solution:The node 4 is stored at location 6.
The nodes are stored in the array in the order of root first then left child of root,right child of root, then left child of child1,right child of child1,then left child of child2 ,right child of child 2 and so on.
Here LCn means left child of node n and RCn means right child of node n.
In array the index starts from 0. so the node 4 is at location 6. but the index value is 5.

4.Comparing to Incomplete Binary Tree,Complete Binary Tree and Full Binary Tree,Which tree is efficient considering space and time complexities?
Solution

Complete Binary Tree
Full binary tree loses its nature when operationas of insertions and deletions are done. For Incomplete Binary trees extra storage is required and overhead of NULL node checking takes place. So complete binary tree is the better one since the property of complete binary tree is maintained even after operations like additions and deletions are done on it.

5.Draw a Binary Tree for the expression A*B-(C+D)*(P/Q)?

Solution


Saturday 13 March 2010

C Bitwise Operators

  • The programming languages are byte oriented but the hardware are bit oriented. so bit level operationas are very important when the program interact directly with the hardware.
  • C provides 6 bitwise operators for bit manipulation.
  • Bitwise operators can only applied to integral operands such as char,short,int and long. these may be signed or unsigned.
  • Bitwise operators can not be applied on floats and doubles.

Operator NameOperator Symbol
bitwise AND&
bitwise inclusive OR|
bitwise exclusive OR^
one's complement(unary)~
left shift<<
right shift>>

  • Consider the bit numbering scheme. The bits are numbered from zero onwards,increasing from right to left
  • for character,the bit representation
  •  For integer(considering int are 16 bits),the bit representation,
  • The bitwise operators are applied to binary numbers ie number consist of 0 and 1. so the integer or char(ascii value) number is converted to binary number for operation. 
  • The program for converting an decimal number to binary number is given below
  • Program to print the binary equivalent of a decimal number

    #include<stdio.h>
    int main()
    {
        int n;
        printf("Enter the number\n");
        scanf("%d",&n);
        dectobin(n);
        return 0;
    }
    int dectobin(int n)
    {
        if(n==0)
            return;
        else
        {
            dectobin(n/2);
            printf("%d",n%2);
        }
    }
1.Bitwise AND(&)
  • The & operator is a binary operator so it requires 2 operands.
  • When the AND operation is performed the 2 operands are compared on a bit by bit basis.So both the operands must be of the same data type (ie both the operands are char or int)
  • The rules for the &  operator is


    First bitSecond bitresult=First bit & Second bit
    00 0
    01 0
    10 0
    11 1
  • Example:
    consider a=10 and b=6. to find a&b
    8bit binary value of a-->0000 1010
    8bit binary value of b-->0000 0110
    result of a&b         -->0000 0010.
    Each bit of a is compared with the corresponding bit in b.If both the bits are set as 1 then the result is 1 else the result is set as 0.Thus the result of a&b=2.
    Note:The operation is performed on individual bits and the operation performed on one pair of bits is completely independent of the operation performed on the other pairs.
  • How to turn off a particular bit? The & operator is used to turn off a particular bit 
  • The & operator is often used to mask off some set of bits.The second operand is called an AND mask.ie using AND operator we can switch off a particular bit..To switch off the 3rd bit the AND mask is created with setting 0 on the 3rd bit and all remaining bit are set as 1.
    ie AND mask=1111 1011
    Example
    binay value of 12--> 0000 1100
    AND mask         --> 1111 1011
    Result           --> 0000 1000(3rd bit is now off)
  • The & operator also used to check whether a particular bit in a number is ON(1) or OFF(0).To find a particular bit for example 3rd bit is ON or OFF the AND mask is  23.ie 8. The binary value of 8 is 0000 1000.The original value is & with this AND mask. In the result if the 3rd bit is 1 then the 3rd bit in the original number is ON. if its 0 then the 3rd bit in the original number is OFF.
    Example:check whether 2nd bit of decimal number 6 is On or OFF.The AND mask is 22 ie 4(0000 0100)
    binary value of 6-->0000 0110
    AND mask         -->0000 0100
    Result is        -->0000 0100.
    The result has 3rd bit as 1. So the 3rd bit on the original number is set as ON.
2.Bitwise OR (or) Bitwise Inclusive OR( | )
  • The Bitwise OR operator is also a binary operator so it requires 2 operands.
  • The rules for the bitwise OR operator is
First bitSecond bitresult=First bit | Second bit
00 0
01 1
10 1
11 1
  • Example: consider a=10 and b=6. to find a | b
    8bit binary value of a-->0000 1010
    8bit binary value of b-->0000 0110
    result of a|b         -->0000 1110.
    Each bit of a is compared with the corresponding bit in b.If either of the bits are set as 1 then the result is 1.If both the bits are 0 then only the result is set as 0.Thus the result of a | b=13.
  • How to turn on a particular bit? Bitwise OR operator is used to turn bits ON. To turn ON a particular bittThe OR mask is created with the particular bit as 1.
    Example
    If you want to set 3rd bit as 1 in the given number 0000 0111(decimal 7) then the OR mask=23 ie 8(0000 1000). This OR mask is OR with original number 0000 0111.
    Binary value of 7-->0000 0111
    OR mask          -->0000 1000
    Result           -->0000 1111.
    if the bit is already ON the OR operation wont alter the value since 1 | 1=1. If the bit is off then the bit is set to ON.
3.Bitwise XOR (or) Bitwise Exclusive OR (^)
  • The XOR operator is a binary operator so it requires 2 operands.
  • The rules for the bitwise XOR is
First bitSecond bitresult=First bit ^ Second bit
00 0
01 1
10 1
11 0
  • XOR operator returns 1 only if one of the two bit is 1.else 0
    Example
    consider a=10 and b=6. to find a ^ b.
    8bit binary value of a-->0000 1010
    8bit binary value of b-->0000 0110

    result of a^b         -->0000 1100.
    Each bit of a is compared with the corresponding bit in b.If either of the bits are set as 1 then the result is 1.If both the bits are 0 or both the bits are 1 then the result is set as 0.Thus the result of a ^ b=12.
  • XOR operator is used to toggle a bit ON or OFF.ie if the bit is 1 set to 0 and if the bit is 0 set to 1.To toggle bits 2 and 3 the XOR mask is created by setting 1 to the 2 and 3rd bit ie 0000 1100. To toggle 0th bit the XOR mask is 0000 0001.
    Example
    To toggle first 4 bits in the decimal number 65
    The XOR mask for toggle 1st 4 bits=0000 1111
    binary value of 65      -->0100 0001
    XOR mask                -->0000 1111
    Result of 65 ^ XOR mask -->0100 1110
  • A number XORed with another number twice gives the original number.
    Exampleconsider a=20 b=10.
    binary value of a   -->0001 0100
    binary value of b   -->0000 1010
    result of a ^ b     -->0001 1110.
    now the result is again XOR with b.
    result of a^b      -->0001 1110
    binary value of b  -->0000 1010
    result of a^b^b    -->0001 0100(20 ie value of a) 
 4.Ones's Complement Operator(~)
  • The one's complement operator is a  unary operator. So it requires only one operand
  • In one's complement of a number, all 1's present in the number are changed to 0'sand all 0's are changed to 0's.
  • The rules are

    bit~bit
    01
    10
  • Example:if a =0000 0000(decimal 0) ones complement of a ie ~a= 1111 1111(decimal 255). If a=1111 1111 then ~a=0000 0000.
5.Left Shift Operator( << )
  • The left shift operator is a binary operator so it requires 2 operands namely left operand and right operand
  • Left shift operator shifts each bit in the left operand to the left. The number of places the bits are shifted depends on the right operand.
  • So A << 1 would shift all bits in A 1 place to the left.A << 3 shift all bits of A in 3 places to the left.
  • When the bits are shifted to the left ,blanks are created on the right.These blanks are always filled with zeros.
  • Example: if A=65 then binary value of A=0100 0001.
    A << 1-->1000 001*
    Now the blank is filled with 0. so A << 1 --> 1000 0010
    A << 2--> 0000 01** so A << 2-->0000 0100
    A << 3-->0000 1000
  • Note:

    1 left shifting is equivalent to multiplication of left operand by 2right operand (ie)A << B =A * 2B
    Example1:
    binary value of 32-->0010 0000
    32 << 1 -->0100 0000( decimal 64 ie 32*2)
    32 >> 2 --> 1000 0000(decimal 128 ie 32 * 22)
    Example2
    binary value of 25 -->0001 1001
    25 << 1 -->0011 0010(decimal 50 ie 25*2 )
    25 >> 2 -->0110 0100(decimal 100 ie 25*22)
 6.Right Shift Operator( >> )
  • The right shift operator is a binary operator so it requires 2 operands namely left operand and right operand
  • Right shift operator shifts each left operand to the right. The number of places the bits are shifted depends on the right operand.
  • So A >> 1 would shift all bits in A 1 place to the right.A >> 3 shift all bits of A in 3 places to the right.
  • When the bits are shifted to the right ,blanks are created on the left.These blanks are always filled with zeros.
  • Example: if A=65 then binary value of A=0100 0001.
      A >> 1-->0010 0000
      A >> 2-->0000 1000
      A >> 3-->0000 0001

  • Note:
  1. If the left operand is a multiple of 2 then shifting the operand to right is same as dividing it by 2right operand

    Example:
          binary value of 128-->1000 0000
          128 >> 1 -->0100 0000( decimal 64 ie 128/2)
          128 >> 2 --> 0010 0000(decimal 32 ie 128/22)
          128 >> 3 -->0001 0000(decimal 16 ie 128/23)
  2. If the left operand is not a multiple of 2 then shifting the operand to right is same as dividing it by 2right operand and ignoring the remainder.
      Example
      binary value of 25 -->0001 1001
      25 >> 1 -->0000 1100(decimal 12 ie 25/2 discarding remainder 1)
      25 >> 2 -->0000 0110(decimal 6 ie 25/4)

  • In A >> B, if B is negative the result is unpredictable.
  • In A >> B, if A is negative then A's left most bit ie sign bit is 1
  • Logical Shift and Arithmetic Shift:
  1. In Logical Shift the high order bits are filled with zero
  2. In Arithmetic shift, the high order bits are filled with the original sign bits. So if the sign bit is 1 then all bits are filled with 1's otherwise they are filled with 0's
  3. For unsigned data types logical shift is used,and for signed data types arithmetic shift is used.



    Friday 12 March 2010

    C Interview Questions

    1.How to write a c program without using semicolon?
    Solution

    1.#include<stdio.h>
    main()
    {
    if(printf("Welcome")){}
    }
    output
    Welcome
    2.#include<stdio.h>
    main()
    {
    while(printf("Welcome"),0){}
    }
    output
    Welcome
    The while loop will execute until the condition is true. so the statement will print continuously to avoid that comma operator is used. The comma operator ignores the 1st argument and return the 2nd one. so the value o is given to while loop and the while loop is executed only once

    2.Write a c program to print the number of digits in a decimal number?
    #include<stdio.h>
    int main()
    {
        int n,count=0,x;
        printf("ENter the decimal number\n");
        scanf("%d",&n);
        x=n;
        while(n>0)
        {
            count++;
            n=n/10;
        }
        printf("Number %d has %d digits\n",x,count);
    }
    output
    ENter the decimal number
    2345
    Number 2345 has 4 digits

    3.Write a C program to print the two's complement of a decimal number?
     Solution
    #include<stdio.h>
    int main()
    {
        int n,x;
        printf("Enter a number\n");
        scanf("%d",&n);
        x=n;
        n=(~n)+1;
        printf("Two's complement of %d=%d",x,n);
        return 0;
    }
    Output
    Enter a number 81
    Two's complement of 81=-81

    C User defined data type

    User defined data type:
    1. typedef
    2. enum
    1.typedef
    • In C language a user can define an identifier that represents an existing data type.
    • The user defined datatype identifier can later be used to declare variables.
    • Syntax is
              typedef datatype identifier;
         
      here datatype represents the existing primary or derived data type. 
    •  Example:
          typedef int marks;
          Now marks can be used  to declare integer variables as
          marks mark1,mark2; 
    2.enum 
    • enum is short form of enumeration 
    • enumeration consists of a set of named integer constants. ie enumeration is a list of constant integer values.
    • Syntax for enum declaration is
              Enum identifier {value1,value2,.....value n}
    • The identifier is a user defined enumerated datatype which can be used to declare variables that have one of the values enclosed with in the braces.
    • after the declaration,we can define variables with this new type as
               enum identifier v1,v2,v3....vn
    • The enumerated variables v1,v2,v3...vn can have only one of the values value1,value2....value n.
    • Example
      declaration
      enum day {Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};
      definition
      enum day day1,day2,day3;

      day1=Monday;
      day2=Friday;

      day3=Sunday;//Error because sunday is not in the enum definition
    • The first name in an enum has value 0, the next has value 1 and so on,unless explicit values are specified. 
    • In the above example Monday is assigned to 0,Tuesday is assigned to 1 and so on and Saturday is assigned to 5 internally.
    • we can also explicitly assign a value to the set
       
      enum day {Monday,Tuesday=0,Wednesday,Thursday,Friday,Saturday};
      The value 0 is associated with Monday by default.Then
      Tuesday is explicitly set to 0.so Wednesday is set to 1 and so on.
    Points to consider:
    1. To explicitly assign an integer value to a variable of an enumerated data type,use a type cast
         enum day today;
          today=(enum day)Monday;
      now today has value 0
    2.  In declaration, enum identifier {value1,value2,.....value n};value1,value2...valuen must all be distinct from each other and different from ordinary variable names,but the values need not be distinct.
          enum student1 {Anand=0,Ashok,Alex} Boys;
          enum student2 {skippy=0,slowvy,Ashok} Girls;
      The above code will create an compiler error because 'Ashok' is available in both the list.
    3. Enum is a set of named integer constant.so while printing the enum members the integer values only printed, Sometimes we need to print the actual name of the enum value for troubleshooting.But we cant directly print the enum members using %s.we can use switch statement or if-else to print the enum values.But if the enum consist of more than 100 constants then the program becomes very large. A simple strategy is to use array of strings(char *)
      Example program to print the enum data
    #include<stdio.h>
    enum new_enum{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
    const char *enum_names[]={"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
    int main()
    {
        enum new_enum e1,e2;
        e1=sunday;
        e2=monday;
        printf("day1=%s\n",enum_names[e1]);
        printf("day2=%s\n",enum_names[e2]);
        return 0;
    }
    Output
    day1=sunday
    day2=monday

    Wednesday 10 March 2010

    C Multidimensional Arrays

    1.Two-Dimensional Array
    • Two dimensional array is also called a matrix.
    • It is taken as an array of an array.
    • Logically the 2 dimensional array 3 X 2 is taken as
      1 2
      3 4
      5 6
      Here there are 3 arrays. one array in each row
    • The values are stored in a row major form. ie each row is stored first. The above array is stored as 1 2 3 4 5 6.
    • Each row array is represented as a[0],which consist of elements 1 and 2.a[1] consists of 3 and 4. and a[2] consists of 5 and 6
    • Each element of a[0] is accessed as a[0][0] and a[0][1].Thus the value of a[0][0]  is 1 and a[0][1] is 2.
    • In memory whether it is a one dimensional or a two dimensional array the array elements are stored in one continuous chain.
    • The size of the array is number of rows * number of columns
    Initializing a 2-Dimensional Array:
    • For initializing a 2-dimensional array we have to specify 2 dimensions. Number of rows and the Number of columns 
    • Ex1:
      int emp[4][3]={
         {1,100,'a'},
         {2,100,'a'},
         {3,98,'b'},
         {4,90,'c'}
      };
    • Ex2: int emp[4][3]={1,100,'a',2,100,'a',3,98,'b',4,90,'c'};
    • While initializing a 2-D array it is necessary to mention the second dimension ie the number of columns.The first dimension ie number of rows is optional.
    • Ex: int a[2][3]={1,2,3,4,5,6}; is same as int a[][3]={1,2,3,4,5,6}; are same. But int a[2][]={1,2,3,4,5,6}; and int a[][]={1,2,3,4,5,6} are wrong way of initializing.
    • In one dimensional arrays name[i] is same as *(name+i). Similarly in 2-dimensional array *(a[2]+1) is same as *(*(a+2)+1).This refer to the 2nd row 1st element.
    • Thus a[2][1] is same as *(a[2]+1) and *(*(a+2)+1)
    Example: passing 2 dimensional array to a function
    #include<stdio.h>
    main()
    {
        int i,j,a[3][2];
        for(i=0;i<3;i++)
        {
            for(j=0;j<2;j++)
            {
                a[i][j]=i;
            }
        }
        printArr(a,3,2);
        printArray(a,3,2);
        return 0;
    }
    void printArr(int a[][2],int m,int n)
    {
        int i,j;
        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            {
                printf("a[%d][%d]=%d is in address=%8u\n",i,j,a[i][j],&a[i][j]);
            }
        }
    }
    void printArray(int (*a)[2],int m,int n)
    {
        int i,j;
        int *p;
        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            {
                p=a+i;
                printf("a[%d][%d]=%d is in address=%p\n",i,j,*(p+j),(p+j));
            }
        }
    }
    Output
    a[0][0]=0 is in address=2609148672
    a[0][1]=0 is in address=2609148676
    a[1][0]=1 is in address=2609148680
    a[1][1]=1 is in address=2609148684
    a[2][0]=2 is in address=2609148688
    a[2][1]=2 is in address=2609148692
    a[0][0]=0 is in address=0x7fff9b847300
    a[0][1]=0 is in address=0x7fff9b847304
    a[1][0]=1 is in address=0x7fff9b847308
    a[1][1]=1 is in address=0x7fff9b84730c
    a[2][0]=2 is in address=0x7fff9b847310
    a[2][1]=2 is in address=0x7fff9b847314


    2.Three-Dimensional Array:
    • Each 3 dimensional array is taken as an array of two-dimensional array
    • Eg: int a[2][3][4]; is a 3 dimensional array. This array consist of 2 arrays of the size 3 X 4. Each array is referred as a[0] & a[1]. Thus a[0] consist of 12 elements and a[1] also consists of 12 elements.
    • The 3 X 4 two dimensional array is then taken as 3 arrays of the size 4.
    • When passing a array to the function,we have to specify the inner dimensions.so while passing this 3 dimension array we have to pass 3 and 4 as inner dimension.
    • The following 2 expressions refer to the same element in the 3 dimensional array
    1. a[1][2][3]
    2. *(*(*(arr+1)+2)+3)
    Example Program:
    #include<stdio.h>
    main()
    {
        int i,j,k,x=0,a[2][3][4];
        for(i=0;i<2;i++)
        {
            for(j=0;j<3;j++)
            {
                for(k=0;k<4;k++)
                {
                    a[i][j][k]=x;
                    x++;
                }
            }
        }
        printArr(a,2,3,4);
        return 0;
    }
    void printArr(int a[][3][4],int m,int n,int p)
    {
        int i,j,k;

        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            {

                for(k=0;k<p;k++)
                {
                    printf("a[%d][%d][%d}=%d is in address=%8u\n",i,j,k,a[i][j][k],&a[i][j][k]);
                }
            }
        }
    }
    Output

    a[0][0][0}=0 is in address=544671328
    a[0][0][1}=1 is in address=544671332
    a[0][0][2}=2 is in address=544671336
    a[0][0][3}=3 is in address=544671340
    a[0][1][0}=4 is in address=544671344
    a[0][1][1}=5 is in address=544671348
    a[0][1][2}=6 is in address=544671352
    a[0][1][3}=7 is in address=544671356
    a[0][2][0}=8 is in address=544671360
    a[0][2][1}=9 is in address=544671364
    a[0][2][2}=10 is in address=544671368
    a[0][2][3}=11 is in address=544671372
    a[1][0][0}=12 is in address=544671376
    a[1][0][1}=13 is in address=544671380
    a[1][0][2}=14 is in address=544671384
    a[1][0][3}=15 is in address=544671388
    a[1][1][0}=16 is in address=544671392
    a[1][1][1}=17 is in address=544671396
    a[1][1][2}=18 is in address=544671400
    a[1][1][3}=19 is in address=544671404
    a[1][2][0}=20 is in address=544671408
    a[1][2][1}=21 is in address=544671412
    a[1][2][2}=22 is in address=544671416
    a[1][2][3}=23 is in address=544671420


    C programs based on Array

    1.Write a program to copy the contents of one array in to another in the reverse order.
    2.If an array name contains n elements,then write a program to check if name[0]=name[n-1],name[1]=name[n-2] and so on.
    3.Write a program to initialize an integer array of 10 elements,pass the entire array to a function multiply() and in multiply(),multiply each element of array by 10 and return the control to main() and print the new array elements in main().
    4.20 numbers are entered from the keyboard into an array. Write a program to find out how many of them are positive,how many are negative,how many are even and how many are odd.
    5.Write a program to search a given number is present in the array or not
    6. Implement the selection sort,bubble sort and insertion sort algorithms on a set of 10 numbers

    Tuesday 9 March 2010

    C Question of the Day -Array

    1.What is the output of the following program?
    #include<stdio.h>
    main()
    {
        char name[]="sun";
        int i;
       for(i=0;name[i];i++)
        {
            printf("%c%c%c%c\n",name[i],*(name+i),*(i+name),i[name]);
        }
        return 0;
    }
    Solution
    ssss
    uuuu
    nnnn

    name[i],*(name+i),*(i+name),i[name] are all different ways of expressing the array element.Here name is the base address.i is the index number


    2.What is the output of the following program?
    #include<stdio.h>
    main()
    {
        int num[]={2.3,3.4,4,5.6,7};
        int i,*x=num,*y=num;
       for(i=0;i<5;i++)
        {
            printf("%d",*num);
            ++y;
        }
        for(i=0;i<5;i++)
        {
            printf("%d",*x);
            ++x;
        }
        return 0;
    }
    Solution
    2222223457Initially pointer num is assigned to both x and y.In the first loop the pointer y is incremented and the num value is printed.So the value 2 is printed 5 times. In the 2nd loop the pointer x is incremented and the value in x is printed. so the integer values 23457 will be printed


    3.What is the output of the following program?
    #include<stdio.h>
    main()
    {
        char str[]="Welcome";
        display(str);
        return 0;
    }
    void display(char *str)
    {
        printf("Text=%s\n",str);
    }
    Solution
    Compiler Error: Type mismatch in redeclaration of function display
    In the main function when the function display is encountered,the compiler doesnt know anything about the function display. It assumes the arguments and return types to be integers(default). But in the actual function display the arguments and the return type contradicts with the assumption. Hence a compile time error occurs.


    4.What is the memory allocated by the following definition?
    [Assuming size of integer is 4 bytes]
    int (*p)[10];
    Solution
    P is a array of 10 integer pointers. 40 bytes memory is allocated


    5.What is the memory allocated by the following definition?
    int (*p)(10);
    Solution
    P is a pointer to a function. size of a pointer is 4 bytes. So 4 bytes memory is allocated.

    Monday 8 March 2010

    C Array

    Introduction:
    • An Array is a collection of similar elements of same data type. The elements may be all int , or all float or all char.
    • we cant create a array with 5 integer element and 5 float elements. 
    • Array elements are referred by using subscript,the lowest subscript is always 0 and the highest subscript is size-1.The valid range of subscript is 0 to size-1
    • Refering an array element using an out of range subscript will produce an error
    • Array elements occupy consecutive memory locations and the size of each element is same.
    • The array name is a pointer constant.we can pass the array name to the function and manipulate array elements in the function.
    • An array is always processed element by element.
    • The array subscript has the highest precedence among all operators.Thus a[2]++,will increment the value at location 2 in the array
    Array Declaration:
            Like other variables array must be declared. The declaration will inform the compiler about the type of array(int,float or char) and the size(Number of elements) of array.
    Syntax:


    data type array_name[size];
    data type-> specifies the type of variable
    array_name -> name of the array variable
    size->number of elements in the array
    []->tell the compiler this variable is a array

    example:
    int a[10];
    float b[5];
    char name[10]; [The array of character is called string]


    Accessing Array elements:
    • All the array elements are numbered starting with 0. This number specifies the elements position in the array.The individual elements in the array can be accessed by specifying array name followed by the position of the element(index) in the array.
    Syntax:

    array_name[index];
    In a[10] array,
    a[0]->First element of the array.
    a[9]->last element of the array.


    • The other way of accessing array elements are:
    1. *(array_name+index)==>*(a+i)
    2. *(index+array_name)==>*(i+a)
    3. index[array_name]==>i[a]
    here i is the index

    Array Initialization:
    The initial value for the array can be given at the time of declaration.

    Syntax:



    data type array_name[size]={value list};

    Ex:

    int numbers[5]={10,20,30,40,50};
    int num[]={1,2,3,4,5,6};
    float count[5]={1.5,3.5,5.6,6.7,7.8};
    char vowels[6]={'a','e','i','o','u','/0'};

    Note:

    1. The characters must be enclosed in single quote(').
    2. The last character in a char array must be a NULL(/0) character.
    3. We can directly assign the string in to a character array.The string must be enclosed in double quotes("). eg: char vowels[6]="aeiou";
    4. When the value assigned to a character array is a string the compiler automatically supplies a NULL character but we need to specify one extra space for NULL character.
    Passing Array Elements to a Function

    • Array elements can be passed to a function by calling the function by value or by reference
    call by value:
    • In the call by value,the values of the array elements are passed to the function.
    • The address can be printed using %16lu(decimal digits) or %p(hexadecimal address)
    • Example:Program to pass array elements using call by value
     #include<stdio.h>
    void printArray(int a[]);
    main()
    {
        int i,a[5];
        for(i=0;i<5;i++)
        {
            a[i]=i;
        }
        printArray(a);
        return 0;
    }
    void printArray(int a[])
    {
        int i;
        for(i=0;i<5;i++)
        {
            printf("%d element is at address %16lu\n",a[i],&a[i]);
        }
    }
    Output
    0 element is at address  140737342687264
    1 element is at address  140737342687268
    2 element is at address  140737342687272
    3 element is at address  140737342687276
    4 element is at address  140737342687280
    • Since each array element is of the integer type,the difference between addresses is 4
    Call by reference:
    • The array members can be passed to the function using call by reference ie passing the base address of the array.Base address is the address of the zeroth element.
    • Each element of the array has a memory address.
    • Example program to passing an entire array using call by reference
    #include<stdio.h>
    void printArray(int *a);
    main()
    {
        int i,a[5];
        for(i=0;i<5;i++)
        {
            a[i]=i;
        }
        printArray(&a);
        return 0;
    }
    void printArray(int *a)
    {
        int i;
        for(i=0;i<5;i++)
        {
            printf("%d element is at address %p\n",*a,a);
            a++;
        }
    }
    output:
    0 element is at address 0x7ffffbd6ac50
    1 element is at address 0x7ffffbd6ac54
    2 element is at address 0x7ffffbd6ac58
    3 element is at address 0x7ffffbd6ac5c
    4 element is at address 0x7ffffbd6ac60
    MORE ABOUT ARRAYS

    Friday 5 March 2010

    C Question of the Day -Preprocessor3

    1.What is the output of the following program?
    #include<stdio.h>
    #define clrscr() 10
    int main()
    {
        printf("result=%d\n",clrscr());
        return 0;
    }
    Solution

    result=10
    #defines are used for textual replacement
    2.What is the output of the following program?
    #include<stdio.h>
    #define fun(f1,f2) f1##f2
    int main()
    {
        int some100=100;
        printf("result=%d\n",fun(some,100));
        return 0;
    }
    Solution

    result=100
    To know about the ## operator Click here

    3.What is the output of the following program?
    #include<stdio.h>
    #define FALSE -1
    #define TRUE 1
    #define NULL 0
    int main()
    {
        if(NULL)
            puts("NULL\n");
        else if(FALSE)
            puts("FALSE\n");
        else
            puts("TRUE\n");
        return 0;
    }
    Solution

    FALSE
    Preprocessor doesnt replace the vaues given inside the double quotes.The check by if condition is boolean value false. so it goes to else if part.-1 is boolean value true. hence it prints FALSE.
    4.What is the output of the following program?
    #include<stdio.h>
    #define max 5
    #define int arr1[max]
    main()
    {
        typedef char arr2[max];
        arr1 list={0,1,2,3,4};
        arr2 name="name";
        printf("%d %s\n",list[0],name);
        return 0;
    }
    Solution

    Compier Error :arr1 undeclared
    arr2 is decared of ype array of size 5 of characters.so it can be used to declare the variable name of the type arr2.But it is not the case of arr1.Hence an error.
    #defines are used for textual replacement whereas typedefs are used for declaring new types.

    5.What is the output of the following program?
    #include<stdio.h>
    #define int char
    main()
    {
        int i=65;
        printf("sizeof(i)=%d \n",sizeof(i));
        return 0;
    }
    Solution

    sizeof(i)=1
    #
    define replaces the string int by the macro char.The size of char is 1 byte

    6.What is the output of the following program?
    #include<stdio.h>
    #define assert(cond) if(!(cond))\
            printf("assertion failed for condition %s\n",#cond)
    main()
    {
        int x=100;
        if(x==100)
            assert(x<100);
        else
            printf("No assert call\n");
        return 0;
    }
    Solution
    assertion failed for condition x<100


    7.What is the output of the following program?
    #include<stdio.h>
    #define assert(cond) if(!(cond))\
            printf("assertion failed for condition %s\n",#cond)
    main()
    {
        int x=100;
        if(x==0)
            assert(x<100);
        else
            printf("No assert call\n");
        return 0;
    }
    Solution
    No output
    The else part in which the printf is there becomes the else for if in the assert macro.Hence nothing is printed.The solution is to use conditional operator instead of if statement.#define assert(cond) ((cond)?(0):printf(""))


    8.What is the output of the following Program?
    #include<stdio.h>
    #define string_def char*
    main()
    {
        typedef char* string_type;
        string_type s1="My",s2="name";
        string_def s3="is",s4="Suni";
        printf("%s %s %s %s\n",s1,s2,s3,s4);
        return 0;
    }
    Solution
    Segmentation Fault
    The preprocessor output is
    main()
    {
        typedef char* string_type;
        string_type s1="My",s2="name";
        char* s3="is",s4="Suni";
        printf("%s %s %s %s\n",s1,s2,s3,s4);
        return 0;
    }
    s4 is of type char not char* so printing s4 as a string produce segmentation fault.

    9.What is the output of the following program?
    #include<stdio.h>
    #define DEF(array,type) sizeof(array)/sizeof(type)
    main()
    {
        int arr[10];
        printf("Total number of array elements=%d",DEF(arr,int));
        return 0;
    }
    Solution
    Total number of array elements=10
    The size of integer array of 10 elements is 10*sizeof(int).The macro expands to sizeof(arr)/sizeof(int)=>10*sizeof(int)/sizeof(int).So the answer is 10


    10.What is the output of the following Program?
    #include<stdio.h>
    #define max main()
    main()
    {
        max;
        printf("Hello Welcome\n");
        return 0;
    }
    1. Compilation error
    2. Preprocessing error
    3. runtime error
    4. executes until the stack overflows
    Solution
    4.executes until the stack overflows