Showing posts with label Fresher Interview Questions on C. Show all posts
Showing posts with label Fresher Interview Questions on C. Show all posts

Saturday, September 21, 2013

How to work with Ellipsis Operator in C Language?

In my last post, I was talking about the printf function and there I said that printf uses ellipsis operator. In this post I would like to elaborate on how to use ellipsis in C program.

a. Here are some important points on Ellipsis
b. Ellipsis operator is expressed only with three dots (…) within the argument list of a function
c. Ellipsis must be the last argument in the argument list
d. The argument list containing the ellipsis must have at least another argument (other than the ellipsis) in the list. Let us call it as “Mandatory Argument”.

This Mandatory Argument must be placed just before the ellipsis and this Mandatory Argument must reflect the number of variable arguments currently being passed explicitly or implicitly.

Here I mean to say, Mandatory Argument can explicitly say that currently n numbers of variable arguments are being passed; in this case the prototype of the function would be something like

void foo(int no_of_variable_arguments, …)

Otherwise Mandatory argument may hide this information within any sort of other data types. For example if the numbers of variable arguments is an element of a structure of type Info, then a valid prototype would be

void foo(struct Info str, …)

If the numbers of variable arguments are passed implicitly then it becomes the responsibility of foo to determine (within the body code of foo) what the value of n from the given container is.

Let us take some more examples

void foo(int var1, int num, …) is a valid usage of ellipsis. Here num is working as Mandatory argument and the numbers of variable arguments actually being passed must be explicitly / implicitly determined through num. var1 is nothing but the optional argument , which might be there for any good reasons.

void foo( char* str, …) is again valid. Here the numbers of variable arguments being passed must be hidden within string str. parsing of str will give you the required value of n. The logic of parsing must be maintained within foo

Let us do a case study on our good old friend printf

The signature of printf is like
int printf(const char* formatString, …)

Here Mandatory Argument does the trick to hide the numbers and types of variable arguments currently being passed.  For example if I call printf like printf(“The results are %d, %d and %f”, I,j,k); then the string  “The results are %d, %d and %f” will implicitly say that there are three variable arguments that are being passed now and they are i, j and k. The proper parsing algorithm in printf will be able to count the numbers of format specifiers like %d or %f and this obviously hides the data types of variable arguments also.  Parsing of “The results are %d, %d and %f” essentially says that there would be three variable arguments and out of these three variable arguments, first two are ints and the third one is float .

Now let us go straight to “how to write the body of the function containing ellipsis as an argument”.

Ellipsis works with four different macros to deal with variable number of arguments; and they are va_list, va_start, va_arg and va_end. The va_list stores the variable arguments. The list is declared like
va_list anyList;

The va_start takes two arguments, the va_list itself and the Mandatory Argument. If the Mandatory Argument passed to the experimental function be integer x, then the call to va_start would be
va_start( anyList, x );
va_start initializes the va_list.

Next va_arg also takes two arguments, va_list itself with a particular data type. For example
va_arg(anyList,float);

Calling of this macro returns the next float from the anyList. 

Ultimately, va_end(anyList) will clean up anyList.

CODE EXAMPLE

The following code example shows how to write a function with variable number of arguments. The
code is self explanatory through commenting. Please give proper attention to the comment in red.

#include<stdio.h>
#include<stdlib.h>
#include <stdarg.h>
//defining the function with variable number of arguments
float findAverage(int numArg, ...)
{
      float avg;
      int sum = 0;
      int arg;
      int index;
      va_list list; //creating the variable list
      va_start(list,numArg); // initializing the list with numAg number of arguments
      for( index = 0 ; index < numArg; index++ )
      {
                  arg = va_arg( list, int );//retrieving the arguments. The prior knowledge of the argument is mandatory. Here in this case it is “int”
                  sum = sum + arg; 
      }
      avg = sum / numArg;
      va_end(list); //clearing up the list
      return avg;
}
int main(void)
{
      //calling the function with variable number of arguments
      printf("\n The average of 3, 4, 5 = %f\n", findAverage(3,3,4,5) );
      printf("\n The average of 6,7,8,9,10 = %f\n", findAverage(5,6, 7, 8, 9, 10));
      return 0;        
}

Thursday, September 19, 2013

In fresher interview technical round, you may get confused with some object oriented "look a like" features of C language.




Sometimes C looks like to follow object oriented paradigm. Don’t get carried away withis idea. Current post focuses on this.

Star (*) Operator in C language acts both as pointer and multiplication. Then could we say that C supports Operator Overloading?

C language certainly does not obey operator overloading. In operator overloading, the function of the operator becomes different, but the arity of  the operator never changes. Here when * acts as a multiplier it is binary in nature, but when it acts as a pointer, it acts as a unary operator. Hence this example never follows the condition of operator overloading regarding the arity of the operator and so by citing this example, we cannot say that C supports operator overloading.

In C language, printf function takes different number and different nature of arguments in every time. Is it the example of Function Overloading?

No way! C does not support function overloading at all. The functions print() is capable of accepting different numbers of arguments due to an operator ellipsis which is represented as … (just three dots, nothing else!)
If we look at the prototype of printf, it would say something like

int printf(const char*, …);

The second parameter is the ellipsis and it uses four different predefined macros va_list, va_start, va_arg and va_end.  Ellipsis essentially says that there could be any number of arguments. This what printf() is backed with, certainly this is not a valid example of function overloading. Because in function overloading the numbers of arguments are specific, for example a function accepting two parameters can be made to accept three parameters (or so), but the instances, two or three are specific. Again in function overloading, the type of parameters can be changed, but once again the set is fixed like a function can act to accept a float and an int, but any data type with function overloading? Just forget it out.

So we are left with to demystify how printf() can accept any data type! This is done by parsing the first parameter of the printf that is const char* which is a string essentially. As we all know, this string contains different format specifiers like %d, %f etc, these specifiers peels out the knowledge that what is type of corresponding argument.

For example if we use

printf(“The results are = %d %f”, i_val, f_val);    

Then in the va_list macro, that is in the list of (v)ariable (a)rgument, there will be two arguments. By parsing the mandatory format string, the type of the first argument is computed as int and the second argument is fixed as float.

Now the question is where is this parsing algorithm present? This algorithm has been implanted within the definition of printf().

In the following post I will show how to use ellipsis operator with code examples.

Monday, September 16, 2013

Lets know about far, near and huge pointers for fresher interview purpose



All of these three candidates relate to 16 bit architecture where segmented memory architecture was there. They are not at all relevant for present days 32 or 64 bit architecture where the way of memory segmentation is completely different; even they may not exist at all.

Still I believe they are good to learn at least for interview purposes. Here I will give you very basic idea of this and I will not encourage you to go beyond that

In 16 bit architecture, the memory is divided into four segments. Data, Code, Stack and Extra and any logical address in this model has two components selector and offset. Selector is used to select the one out of four logical segments and the offset is used to point the address within the segment as specified by the selector.

On this background, a far pointer (designated by a non standard keyword “far”) can point across the segment as the selector portion of its logical address is explicitly represented. The offset represent the distance from the base of the selector. The arithmetic operations on the far pointers are not allowed to change selector portion, only the offset portion can be changed.

On the other hand, a near pointer can point only to the current segment, hence it has got no explicit selector, only the offset value is there and it is free to be changed through pointer arithmetic.

A huge pointer is like far pointer where explicit selectors are there, but the point of its difference with far pointer is that it is normalized. This means, as pointer arithmetic (in both the cases of far and huge) can change the offset part; it may go beyond the current selector range. In case of far pointer even if the offset is changed to different selector, selector will not be changed, but in case of huge pointer, the selector will be changed to wrap around the offset value, and the offset value will be minimum. This wrapping off selector portion is called pointer normalization.