Coupon Accepted Successfully!


Question 1

What is the difference between statically linked libraries and dynamically linked libraries (dll)?

Static linking means all the referenced code is included in the binary produced. When linking statically, the linker finds the bits that the program modules need, and physically copies them into the executable output file that it generates.

Incase of dynamic linking, the binary simply contains a pointer to the needed routine, which will be loaded by the OS as needed. An important benefit is that libraries can be updated to fix bugs or security problems and the binaries that use them are immediately using the fixed code. It also saves disk space, saves memory usage, saves launch time, improve multi-tasking efficiency. But, deployment of dynamically-linked executable generally requires coordination across hosts of shared-object libraries, installation locations, installation environment settings, settings for compile-, link-, and use-time environment variables Dynamic linking often precludes relocations backward across OS versions.

On Linux, static libraries have names like libname.a, while shared libraries are called libname.so.x.y.z where x.y.z is some form of version number. Shared libraries often also have links pointing to them, which are important, and (on a.out configurations) associated .sa files. The standard libraries come in both shared and static formats. You can find out what shared libraries a program requires by using ldd (List Dynamic Dependencies)

Dynamic linking allows an exe or dll to use required information at run time to call a DLL function. In static linking, the linker gets all the referenced functions from the static link library and places it with your code into your executable. Using DLLs instead of static link libraries makes the size of the executable file smaller. Dynamic linking is faster than static linking.

Question 2

What are the most common causes of bugs in C?

Murphy's law states that "If something can go wrong, it will. So is the case with programming. Here are a few things than can go wrong when coding in C.

  • Typing if(x=0) instead of if(x==0). Use if(0==x) instead.
  • Using strcpy() instead of strncpy() and copying more memory than the buffer can hold.
  • Dereferencing null pointers.
  • Improper malloc(), free() usage. Assuming malloc'ed memory contains 0, assuming freed storage persists even after freeing it, freeing something twice, corrupting the malloc() data structures.
  • Uninitialized local variables.
  • Integer overflow.
  • Mismatch between printf() format and arguments, especially trying to print long ints using %d. Problems with wrong arguments to sprintf() leading to core dumps.
  • Array out of bounds problems, especially of small, temporary buffers.
  • Leaving files opened.
  • Undefined evaluation order, undefined statements.
  • Omitted declaration of external functions, especially those which return something other than int, or have
    "narrow" or variable arguments.
  • Floating point problems.
  • Missing function prototypes.

Ofcourse, there is the mother of all things that can go wrong - Your logic!.

Question 3

What is the difference between the stack and the heap? Where are the different types of variables of a program stored in memory?

When a program is loaded into memory, it is organized into three areas of memory, called segments: the text segment, stack segment, and the heap segment. The text segment (sometimes also called the code segment) is where the compiled code of the program itself resides. This is the machine language representation of the program steps to be carried out, including all functions making up the program, both user defined and system.

The remaining two areas of system memory is where storage may be allocated by the compiler for data storage. The stack is where memory is allocated for automatic variables within functions. A stack is a Last In First Out (LIFO) storage device where new storage is allocated and deallocated at only one "end", called the Top of the stack. When a program begins executing in the function main(), space is allocated on the stack for all variables declared within main(). If main() calls a function, func(), additional storage is allocated for the variables in func() at the top of the stack. Notice that the parameters passed by main() to func() are also stored on the stack. If func() were to call any additional functions, storage would be allocated at the new Top of stack. When func() returns, storage for its local variables is deallocated, and the Top of the stack returns to its old position. If main() were to call another function, storage would be allocated for that function at the Top. The memory allocated in the stack area is used and reused during program execution. It should be clear that memory allocated in this area will contain garbage values left over from previous usage.

The heap segment provides more stable storage of data for a program; memory allocated in the heap remains in existence for the duration of a program. Therefore, global variables (storage class external), and static variables are allocated on the heap. The memory allocated in the heap area, if initialized to zero at program start, remains zero until the program makes use of it. Thus, the heap area need not contain garbage.

Question 4

Describe the memory map of a C program.

This is a quite popular question. But I have never understood what exactly is the purpose of asking this question. The memory map of a C program depends heavily on the compiler used.

Nevertheless, here is a simple explanation..

During the execution of a C program, the program is loaded into main memory. This area is called permanent storage area. The memory for Global variables and static variables is also allocated in the permanent storage area. All the automatic variables are stored in another area called the stack. The free memory area available between these two is called the heap. This is the memory region available for dynamic memory allocation during the execution of a program.

|                       |
|  Automatic Variables  | --> Stack  
|                       |
|                       |
|                       |
|     Free Memory       | --> Heap
|                       |
|                       |
|                       |
|   Global Variables    | --+--> Permanent storage area 
|                       |   |
+-----------------------+   |
|                       |   |
|     Program (Text)    | --+
|                       |

Question 5

What is infix, prefix, postfix? How can you convert from one representation to another? How do you evaluate these expressions?

There are three different ways in which an expression like a+b can be represented.

Prefix (Polish)


Postfix (Suffix or reverse polish)




Note than an infix expression can have parathesis, but postfix and prefix expressions are paranthesis free expressions.

Conversion from infix to postfix

Suppose this is the infix expresssion

((A + (B - C) * D) ^ E + F)

To convert it to postfix, we add an extra special value ] at the end of the infix string and push [ onto the stack.

((A + (B - C) * D) ^ E + F)]


We move from left to right in the infix expression. We keep on pushing elements onto the stack till we reach a operand. Once we reach an operand, we add it to the output. If we reach a ) symbol, we pop elements off the stack till we reach a corresponding { symbol. If we reach an operator, we pop off any operators on the stack which are of higher precedence than this one and push this operator onto the stack.

As an example

Expresssion                          Stack                    Output
((A + (B - C) * D) ^ E + F)]      [

((A + (B - C) * D) ^ E + F)]      [((                         A

((A + (B - C) * D) ^ E + F)]      [((+                        A

((A + (B - C) * D) ^ E + F)]      [((+(-                      ABC        

((A + (B - C) * D) ^ E + F)]      [(                          ABC-D*+

((A + (B - C) * D) ^ E + F)]      [(                          ABC-D*+E^F+

((A + (B - C) * D) ^ E + F)]      [                           ABC-D*+E^F+

Is there a way to find out if the converted postfix expression is valid or not

Yes. We need to associate a rank for each symbol of the expression. The rank of an operator is -1 and the rank of an operand is +1. The total rank of an expression can be determined as follows:

- If an operand is placed in the post fix expression, increment the rank by 1.
- If an operator is placed in the post fix expression, decrement the rank by 1.

At any point of time, while converting an infix expression to a postfix expression, the rank of the expression can be greater than or equal to one. If the rank is anytime less than one, the expression is invalid. Once the entire expression is converted, the rank must be equal to 1. Else the expression is invalid.

Conversion from infix to prefix

This is very similar to the method mentioned above, except the fact that we add the special value [ at the start of the expression and ] to the stack and we move through the infix expression from right to left. Also at the end, reverse the output expression got to get the prefix expression.

Evaluation of a postfix expression

Here is the pseudocode. As we scan from left to right

  • If we encounter an operand, push it onto the stack.
  • If we encounter an operator, pop 2 operand from the stack. The first one popped is called operand2 and the second one is called operand1.
  • Perform Result=operand1 operator operand2.
  • Push the result onto the stack.
  • Repeat the above steps till the end of the input.

Convert from postfix expression to infix

This is the same as postfix evaluation, the only difference being that we wont evaluate the expression, but just present the answer. The scanning is done from left to right.





Convert from postfix expression to infix

The scanning is done from right to left and is similar to what we did above.


Reverse it





Question 6

How can we detect and prevent integer overflow and underflow?

This questions will be answered soon :)

Question 7

What is hashing?

Hashing is the process of mapping strings to integers, in a relatively small range.

A hash function maps a string (or some other data structure) to a bounded number (called the hash bucket) which can more easily be used as an index in an array, or for performing repeated comparisons.

A mapping from a potentially huge set of strings to a small set of integers will not be unique. Any algorithm using hashing therefore has to deal with the possibility of collisions.

Here are some common methods used to create hashing functions

Direct method
Subtraction method
Modulo-Division method
Digit-Extraction method
Mid-Square method
Folding method
Pseudo-random method

Here is a simple implementation of a hashing scheme in C

#define HASHSIZE 197

typedef struct node
  int value;
  struct node *next;

typedef struct hashtable
  mynode *llist;

HT myHashTable[HASHSIZE];

int main()


int initialize()
  int i;
  for(i=0;i      myHashTable[i].llist=NULL;

int add(int value)
  int hashkey;
  int i;
  mynode *tempnode1, *tempnode2, *tempnode3;
  printf("\nHashkey : [%d]\n", hashkey);

      //This hash bucket is empty, add the first element!
      tempnode1 = malloc(sizeof(mynode));
      //This hash bucket already has some items. Add to it at the end.
      //Check if this element is already there?
            printf("\nThis value [%d] already exists in the Hash!\n", value);

    tempnode2 = malloc(sizeof(mynode));
    tempnode2->value = value;

int display_hash()
  int i;
  mynode *tempnode;

  for(i=0;i   {
        printf("\nmyHashTable[%d].llist -> (empty)\n",i);
        printf("\nmyHashTable[%d].llist -> ",i);
           printf("[%d] -> ",tempnode->value);

And here is the output

Hashkey : [2]

Hashkey : [136]

Hashkey : [2]

Hashkey : [2]

This value [2] already exists in the Hash!

myHashTable[0].llist -> (empty)

myHashTable[1].llist -> (empty)

myHashTable[2].llist -> [2] -> [199] -> (end)

myHashTable[3].llist -> (empty)

myHashTable[4].llist -> (empty)

myHashTable[5].llist -> (empty)

myHashTable[6].llist -> (empty)

myHashTable[7].llist -> (empty)

myHashTable[8].llist -> (empty)

myHashTable[9].llist -> (empty)

myHashTable[10].llist -> (empty)

myHashTable[11].llist -> (empty)

myHashTable[12].llist -> (empty)

myHashTable[13].llist -> (empty)

myHashTable[14].llist -> (empty)

myHashTable[15].llist -> (empty)

myHashTable[16].llist -> (empty)

myHashTable[17].llist -> (empty)

myHashTable[18].llist -> (empty)

myHashTable[19].llist -> (empty)

myHashTable[20].llist -> (empty)


myHashTable[133].llist -> (empty)

myHashTable[134].llist -> (empty)

myHashTable[135].llist -> (empty)

myHashTable[136].llist -> [2500] -> (end)

myHashTable[137].llist -> (empty)


myHashTable[196].llist -> (empty)

Question 8

What is data structure?

A data structure is a way of organizing data that considers not only the items stored, but also their relationship to each other. Advance knowledge about the relationship between data items allows designing of efficient algorithms for the manipulation of data.

Question 9

What are the time complexities of some famous algorithms?

Here you are

Binary search                                :    O(logn)
Finding max & min for a given set of numbers :    O(3n/2-2)
Merge Sort                                   :    O(nlogn)
Insertion Sort                               :    O(n*n)
Quick Sort                                   :    O(nlogn)
Selection Sort                               :    O(n*n)

Question 10

What is row major and column major form of storage in matrices?

This is row major representation

If this is your matrix

a b c d
e f g h
i j k l

Convert into 1D array by collecting elements by rows. Within a row elements are collected from left to right.
Rows are collected from top to bottom. So, x[i][j] is mapped to position i*no_of_columns + j.

This is column major representation

On similar lines, in column major representation, we store elements column wise. Here, x[i][j] is mapped to position i + j * no_of_rows.


Test Your Skills Now!
Take a Quiz now
Reviewer Name