Sunday, July 13, 2008
Read these C statements
1> int *a
2> int **a
3> int *a()
4> int (*a)()
5> int *a[5]
6> int (*a)[5]
7> int (*a())[5]
First one is obvious. All of us know a is a pointer to an integer.
<2> is again simple. a is a pointer to pointer to an integer
<3> Here a is a function whose return type is int pointer
<4> a is pointer to function which has no parameters and which returns an integer. Now you know how to write function pointers. Remeber to enclose the * along with function name in paranthesis.
<5> a is an array of 5 integer pointers
<6> a is pointer to an array of 5 integers. This is equivalent to a 2 dimensional array. Now do some home work. Compile a program with a function which takes a 2d array as a parameter (say
void print(int a[3][3])
with debugging enabled (as gcc prg.c -g). Start gdb and enter the function. Now ask the gdb whatis 2d array
gdb> whatis a
type int (*a)[3]
So gdb is telling you your parameter is a pointer to an array. This is one concept many of us misunderstand. Since 1d array gets converted into pointer when passed as a parameter, we think 2d array gets converted into pointer to pointer. NO, IT DOES NOT. It gets converted into a pointer to an 1d array, this pointer pointing to the first row. By incrementing the pointer, we get the second row.
<7> Here is a function which returns a 2d array. Now you will think how can a function return an array? No, the function is returning a pointer to an array, which is nothing but address of first row of the 2d array.
Let us write a function to return a matrix after doubling it and without modifying the original matrix
int (*doubleElements(int c[3][3])[3]
{
int d[3][3];
int i,j;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
d[i][j]=c[i][j]*2;
return b;
}
Please note that int d[3][3] can also be written as int (*d)[3].
Now the more difficult part is how to accept the matrix returned by this function.
int a[3][3],b[3][3];
-------
-------
b=doubleElements(a);
-------
-------
Now tell me why this wont work. b is the base address of the array and hence can not be used on LHS. So let us rewrite it as
int a[3][3], (*b)[3];
Fine we are ready to test the program.Do we get the output. NO. We get some garbage values. Why?
Look at the life span of d. This array is valid as long as the function exists. And is popped out the moment you return from function. It is destroyed and we are returning this destroyed array.
Only way to overcome this problem is declare d as a static array.
static int (*d)[3];
Now static elements are not stored in data segment and hence are not destroyed when function returns.And now our prgram works!!!
Thursday, July 3, 2008
Functions (2)
Exercise 1: Search for the file stdio.h and see the contents of the file
A function declaration as well as the header of the function must specify the name of the function, parameter list and also return type. If you do not mention the return type, c compiler assumes that the function returns an int.
float findHalf(int n)
{
return (n/2.0);
}
Now define this function after defintion of main(). Now call this function say
What do answer do you obtain? 7.5? 7? No. Answer will be zero.
findHalf(int );
You don't see change in the output. Again since you haven't mentioned return type, compiler thinks it is an int function.
float findHalf(int );
This declaration gives you the correct answer.
Ex 2: Write a program to print how many days are left for you on this earth making an assumption that you live upto 80 years. OK, ok, if you think it is too morbid, write a program to print how many days old are you.
Let us write some bit manipulation programs which Ritchie is so fond of. First write a function to find the number of 1 bits in the given int.
int numBits(unsigned int n )

Now look at this image fro http://www.oaklib.org/ which shows the ways stack frames are organised when 3 functions are being called.
Sunday, June 29, 2008
Functions In C
Another feature of C functions are, they are a self contained blocks. All variables defined inside the functions are local to the function. Even the parameters sent by caller are sent as copies without affecting the original values.
C does not distinguish between procedures and functions like Pascal. If a function is meant to execute statements and not return an answer, it is supposed to return void. Note here that void is also a data type. But you can have only void functions and pointers but not have void variables.
A C function can return only one value. This return value can be any built in or extended data type except for an array. A FUNCTION CAN NOT RETURN AN ARRAY. NOR CAN IT RETURN ANOTHER FUNCTION. If there is a need to return an array, then the function can be made to return a pointer because of similarities between array and pointer.
C functions are isolated from each other. A function can not use variables defined in other functions. It can only use local variables or so called global variables which are variable defined outside of all functions.
In order to use a function, three steps are needed. 1> Declare a function 2> Define a function 3> Invoke a function. Declaration is like a variable declaration. It tells the type of function (ie type of its return value) and type and number of its parameters. Function declaration is function header with a semicolon.
If a function is not declared, it is assumed to be a function which can take any number of parameters and which returns an int. Note int not void. Hence many students have the practice of writing main() instead of int main(). But that is OK when compared to the blunder of writing void main(). Never write void main(). main function returns an integer which is the exit status of the program.
A function can call itself. Then it becomes a recursive function. These recursive functions are useful for solving some algorithms. But if a recursive call is the last statement of a function, then it is tail end recursion which should be avoided. As a rule of thumb, you should use recursion only when iterative solution is too compicated.
A function creates a stack frame when it is invoked. This frame will store all local variables, parameters etc. When the function is returned, the stack frame is removed. This is an advantage, as the variable take up memory only when they are in use. But it will not be possible to remember the previous value of local variable. For that you must use a static variable.
Every C program has a special function called main(). This function is the starting point of the program for hosted environments. Other functions do get executed when they are called by main directly or indirectly.
main() can accept parameters in the form of command line arguemnts. These are a series of strings supplied with the exec file name. They will be stored in array of strings normally called argv (argument vector) and their count will be stored in argc.
An array gets passed to the function as call by address method unlike other types of parameters which are passed as copies (ie call by value). If the function modifies array parameter in the function, the actual parameter array also gets modified (For any other type of parameter, this does not happen). The reason for this is, the function treats array parameter as a pointer to first element of the array and manipulates the array using this pointer.
Note that in any expression (except for sizeof operator) which uses an array, the array gets converted into pointer.
Tuesday, June 3, 2008
Deep copy and shallow copy
Deep copy will allocate memory for these members then copy the contents not the pointers.
Point to note here is Compiler provided assignment operator as well as copy constructor will perform shallow copy.
This article clearly explains the difference between deep and shallow copying of objects.
http://www.fredosaurus.com/notes-cpp/oop-condestructors/shallowdeepcopy.html
Now for an example
#include
using std::cin;
using std::cout;
using std::endl;
//class definition
class deep
{
public:
int *m;//this has to be dynamically allocated
void print();
};
void deep::print()
{
cout<<"The number is "<<*m<< endl;<>
int main()
//create two objects of deep class
//copy to d2
//print d1 and d2;
cout lt<"D2 is ";
//Now change d2
//again print d1 and d2
cout<<"D2 is \n";
return 0; //successful termination of the program
deep::~deep()//destructor
//assignment operator for deep copy
int main()
//create two objects of deep class
//copy to d2
//print d1 and d2;
cout<<"D2 is ";
//Now change d2
//again print d1 and d2
cout<<"D2 is \n";
return 0;//successful termination of the program
Where are C++ objects stored?
Answer : A class is nothing but data type description. Which is present in the code. So I don't think the class will have any memory allocated to it.
As far as object is concerned, the object will be stored in stack if it is a local object, in heap if it is dynamic object and in data segment if it is a static object.
How are the methods i.e. function members of the object stored. They are NOT stored as objects have pointers to actual function. In fact there is a single function per class in the code segment. In that situation how does the function access the data members of the object. This is achieved with a special pointer this which gets passed to the function.
A static member function is special because it does not get this pointer. So it CAN NOT access the non-static data of the object.
And a virtual function is handled in another way. Here every object which has atleast one virtual function will have a special pointer vptr which points to vtbl a per class table which holds the address of all virtual functions.
Read a better description of all this in
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=195
Monday, June 2, 2008
Sequence point
What will be the output of the following program in UNIX OS with CC compiler and TC compiler?
int main()
{int i=5;
printf("\n%d",++i + ++i + ++i + ++i + ++i );
}
If any difference then Why it is difference?
The answer is the program is wrong. Unfortunately the program will compile and run and show some result.
According to C standard you can not modify the variable more than once in between two sequence points. Here you are modifying the variable i 5 times. Please note that + addition operation is not a sequence point. Only logical operator && and and the complete expression and function call are sequence points.
At a sequence point, all variable updates and side-effects since the previous sequence point are guaranteed to have taken place.
Read more about sequence points here.
http://c-faq.com/expr/seqpoints.html
and here http://en.wikipedia.org/wiki/Sequence_point . There is one more link to "THe C book" But currently i am unable to open it.
Sunday, May 4, 2008
Some light moments
http://mukthabalaga.wordpress.com/category/it-junk/
THis is a piece of a joke site.
You Might Be a Programmer if...
you lust for O'Reilly books.
you know that "goto considered harmful".
you are looking for the "else" at the end of this joke.
you believe that making a wrong program worse is no sin.
every combination of three letters is a meaningful acronym for you.
when you are counting objects, you go "0,1,2,3,4,5,6,7,8,9,A,B,C,D...".
you can remember seventeen computer passwords but not your anniversary.
you are sure that the year 2000 is a leap year, and know why it is dangerous.
you start laughing hysterically when the topic of computer reliability is brought up.
you go to balance your checkbook and discover that you're doing the math in hexadecimal.
the language you are best speaking is English, but the language you are best writing is Java.
on vacation, you are reading a computer manual and turning the pages faster than everyone else who is reading John Grisham novels.
Thursday, April 17, 2008
Some tips on C Operators
1> One divided by 3 is 0?
What is the value of m here ?
int n=1;
int p = 3;
float m;
m = n/p;
Did you say 0.3333. The answer is wrong. m is zero. You see here n and p are integers. Hence n/p gives integer result which is 0. Now m is assigned to 0.00.
float p = 2 ,q;
int m,n;
m=1; n=3;
q = m/n * p;
Now tell me what is the value of q in the above code. Don't tell me that it is 0.6667. It is again zero. Now you may think that as p is a non-integer, the calculation should happen in floating point arithmetic. But that happens after m/n is performed. In a division if both numerator and denominator are integers, result is a truncated integer. This zero is now multiplied by 2 which again gives 0.
2> Modulo operator does not compile ?
float a = 2;
int m = 15 % a;
What is the value of m? It is not 1. The code produces a syntax error which says something like '%' : illegal, right operand has type 'float'. Because Both operands for % operator should be integers.
3> Division by zero is not caught by compiler
float p = 2 ,q;
int m,n;
m=1; n=0;
q = m/n * p;
Do you think 4th line in this code produces syntax error and saves you from further trouble. No. C compilers think you programmers are very smart and even very careful. So the code compiles and then executes and gives a run time exception division by zero. Always ensure that your denominator is not zero.
4> Lazy evaluation
Let us ensure that denominator is not zero when performing a division
float p = 2 ,q;
int m,n,s=3;
m=1; n=0;
if (s == m/n && n!=0)
printf("%d",s);
else
printf("Denominator is zero.");
OK, we have taken care of checking denominator is non-zero. Are we saved? Not yet. This also produces run time error for s==m/n.
Let us interchange the operands of && operator , because && is cumulative i.e. A&&B is same is B&&A. Now our code is
float p = 2 ,q;
int m,n,s=3;
m=1; n=0;
if (n!=0 && s==m/n)
printf("%d",s);
else
printf("Denominator is zero.");
Now the code runs correctly. What went right? Well this is called lazy evaluation. Logical and and or operators have left to right associativity (i.e. they are evaluated from left to right) and the evaluation stops when an unambiguous answer is obtained. If n is zero, first condition is false and irrespective of second condition, the result will be false. Hence C does not evaluate the second operand. So no division by zero and no run time error.
In situations like these, lazy evaluation (also called short circuiting) comes to your rescue.
Last question.
5> Isn't -2 less than 4 ?
May not be.
t = -2 "<" sizeof(int);
Sizeof int is 4 for all 32 bit processors. So -2"<"4 ? Is true. So t must be true that is 1. No! You get t as 0? Howzzat?
sizeof operator yields an unsigned integer. Now < operator has one operand -2 as int and another sizeof(int) as unsigned int which is larger data type. So compiler converts both operands into unsigned. -2becomes 0xfffffffe when converted to unsigned. This is certainly not less than 4. Hence the result.
Tuesday, April 1, 2008
C data types
When someone asks you in an interview, how many data types are present in C, you will start counting your fingers int, short int, unsigned int, double, float etc. But the right answer might be
There are 4 data types in C which are int, float, char and double.
Now what about short, long etc. Well, these can be called as data type modifiers. These can be used with int as
Long int
Short int
Unsigned int
Signed int
Long unsigned int
Short unsigned int
And with char as
Signed char
Unsigned char
int data type
You all know what is an int. It is a basic number without any fractional information which will be stored internally in binary (have to tell). Now what about negative integers? How are these stored? C stores these in either 1’s complement or 2’s complement format. This needs one bit which is MSB for storing the sign of the number (1 –indicates negative and 0 indicates positive ). Hence the largest number which can be stored will be not as big as you expect. (e.g. if an int is stored using 16 bits, the largest int which can be stored is not 216 -1 but instead 216-1 – 1.
Now how big is an int. Well it is not infinity because computer should store and manipulate the numbers using CPU registers which are having limited bit length. That is exactly how big is an int as big as a register (or in other words the size of an int is word length of the computer). This Turbo C has set a misconception in students. Turbo C shows size of an int as 16 bits or 2 bytes even on a Pentium machine which is 32 bit processor. So students will either think an int is 2 bytes or at the most they may say int size depends on the compiler. No, int size does not work on the compiler. But turbo c works in real mode which is compatible with X86 i.e. 16 bit processor. [u1] Hence all this confusion. Find the size of int in Visual c++ compiler in Windows or gcc compiler to get the correct picture.
The size of an int is word size of the computer
Now what are the differences between short, long and unsigned and signed ints. Well ANSI standard does not say much. It just says that
Sizeof short int<=sizeof int<=sizeof long int Most of the implementations provide short int as 16 bits and long int as 32 bits. Now unsigned prefix will make the range from 0 to 2Xmax as that of ordinary int, or short int or long int. Please keep in mind that default is signed. You can also define variables as short a; unsigned long b; These are valid because C adds default int to these variable declarations. (Remember if a function type is not declared, it is treated as a function returing int -- For that matter even if we declare static m; M is treated as static integer. Int literals can have only digits 0 to 9. If the int literal has 0 as a prefix, then it is treated as an octal value. Similarly if the int literal has 0x as prefix, it is treated as hexadecimal value. (If you already do not know, in hexadecimal a-f or A-F represent 10 to 15) If an int literal has a suffix of l, then it’s a long integer. If it has suffix of u, it is unsigned integer. Question : Which of the following are valid integers in a 16 bit computer. 40000 0890 0xabcd char data type char in C stored using some code normally ASCII. This is a 7 bit code. Size of a char is always 1 byte. Now a char is stored as an integer which represents the given character in the given coding scheme. i.e. the alphabet ‘A’ is stored as 65 A character literal should be enclosed in single quotes. char c =’A’; Some of the characters can not be typed. E.g. how do you type enter key which will take the cursor to next line. Or how do you type tab character. Such characters have some escape sequences. Escape sequences are char constants which start with backward slash. Some of the escape sequences are ‘\t’ tab ‘\n’ new line character ‘\r’ carriage return ‘\f’ form feed ‘\b’ bell ‘\nnn’ character whose code in octal in nnn char is an integer data type. That is to say it can be used in any arithmetic calculation. char c =’A’; int m=c+2; Now the value of m will be 67. A char can also be used in a for loop. Char can use datatype modifier signed and unsigned. Unsigned char will have a range from 0 to 255 whereas a signed char will have a range from -128 to 127. If we use a char variable without these modifiers, do we get a signed char or unsigned char ? That does depend on the implementation. So if you want to write portable programs, always explicitly specify signed/ unsigned. Another thing to remember here is any char variable in an expression is converted into int. Hence you will notice that sizeof(‘A’) is 4 bytes (on a 32 bit processor) instead of 1 byte. (In C++ this size is 1 byte because c++ is strongly typed language) When do you use a char. Obviously when you want to use non-numerical information. But please remember a char can not store your complete name. Name is not a character. It has many characters. Such strings have to be stored using an array of characters. char a[10]=”Usha”; A string literal should be enclosed within double quotes. float data types floating point data types are fractional numbers. They are so called because you can move around the decimal point by varying the exponent. Normally these numbers are stored in two parts – viz mantissa and exponent. E.g. if the number is 1.7e-5 then mantissa is 1.7 and exponent is -5. And by the way its value is 0.0000175. These float numbers can be stored only with limited precision. Now if the number can be stored with 6 digits precision, then the number will be accurate for first 6 digits. Double data type will normally have double the precision of the float type. All float arithmetic calculations are performed in double precision. And in any expression a float will be converted to double. Now C standard does not mention anything about how a float has to be stored. But most compilers use IEEE 754 standard. This stores the mantissa in normalized form and exponent by adding 127 for float and 1024 for double[u2] . The header file float.h will have macros FLT_MAX, FLT_MIN, FLT_DGT, DBL_MAX etc.
Always keep in mind that floats are not very accurate. Hence you should be careful when comparing a float for equality. Check this program.
float a = 1.7;
if (a==1.7)
printf(“Equal”);
else
printf(“Unequal”);
float literals can be written either in decimal notation or scientific notation with e or E specifying exponent to the base 10. A float literal by default is double literal. To make it float, suffix with f or F.
float a = 1.7f;
Hence size of a 1.7 will be 8 bytes (which is the size of double) rather than 4 bytes.
Exercises :
1> Find the sizes of unsigned int , short int and long int, double and float
Hint : use sizeof operator
2> Find the maximum, minimum short and long integer and unsigned integer without using loop
Hint : Use limits.h file
3> Find out whether your compiler uses signed char as default or unsigned char.
Tuesday, March 11, 2008
Size of an empty struct
When I was teaching, some students used to ask me a question. Why is size of an empty struct 1 in C++ and 0 in C ? I coded and found out that gnu compiler does give this result whereas other compilers like tc and vc++ give an error for empty structure in c ? What is the reason?
#include
struct emptystr
{
};
int main()
{
printf(“%d”,sizeof(struct emptystr));
}
Compile it under gcc. The answer is 0 and under g++ answer is 1.
It can be explained like this . Let us say an empty struct has a size of zero. Then two adjacent variables of this structure type must have the same address. Address of any variable must be unique. Hence it is not possible to have size of any variable or data type as zero.
Then how do you explain the fact that in C, size is 0. The actual reason is, according to ANSI standard, sizeof operator can not be applied to incomplete data types. An empty structure is incomplete. Hence 0 we are getting is garbage. Try to compile this program with flag –pedantic-errors. You will get a syntax error.
gcc emptystr.c –pedantic-erros
You will get an error which says struct has no members.
Then how is empty structure valid in C++ ? C++ being OOP language, a structure can contain methods as well as data members. Even though the structure has no data members, there are at least a constructor and destructor which are supplied by compiler.
Hence the type is not incomplete. (well it is in fact similar to a structure or class with only function members )
struct onlyfuntcions{
void print()
{
Cout<<”Hello”;
}
};
Size of this structure in c++ is also 1 byte.
Now don’t get scared. You did not know that a struct can also have constructor?? It can have. Struct in C++ is very much similar to class. The only difference between the two is struct members by default are public where as class members by default are private.
Books for c
The former is meant for kids ( or kids in c) and latter is for pro who already knows everything in C. Let us C is easy to understand but it should not be used after you learn the alphabets of C. K&R is good but cryptic. Now you have learnt the alphabets, but not mastered the grammars and prose and verse of the language. So how do you bridge the gap ? Or which book bridges the gap. Now there are Balaguruswamys, Stephen Cochens etc. Along with these there is c-faq, a set of very good questions and good answers to them by Steve summit. It helps a lot.
Recently I have come across a book called C in a Nutshell by Peter Prinnz. This is again a reference. You should not expect lengthy explanations or solved programs. But all the concepts are given and without any ambiguity. THe book also covers ANSI-99.