Sunday, December 18, 2011

inline function : Demo

Inline expansion, or inlining, is  compiler optimization that replaces a function call site with the body of the callee. This optimization may improve time and space usage at runtime, at the possible cost of increasing the final size of the program (i.e. the binary file size).

#include <iostream>

using namespace std;

inline int square(int n)
{
   return  n*n;
}

int main()
{
   int x = 5, sq;
   sq = square(x);
   //
   //  At this call, x*x is replaced by compiler.
   //

   cout << sq << endl;

   return 0;
}


"inline" is just a hint or request to compiler to expand the body of function at its call.
Compiler may decline this request, often in following cases:
1. Function returning a value, contains loop, switch or goto.
2. Function not returning value, has a return statement.
3. Function contains a static variable.
4. Function is recursive.

Function overloading : _Z10Everything _Z4that _Z5looks _Z6simple, _Z2is _Z3not_Z8 actually _Z2so !

#include <iostream>
using namespace std;

int add (int a, int b);
float add (float a, float b);

int main()
{
  int a = 6;
  int b = 3;

  float c = 5.46;
  float d = 7.887987;

  cout << a << "+" << b << "=" << add(a,b) << endl;
  cout << c << "+" << d << "=" << add(c,d) << endl;

  return 0;
}

int add(int a, int b)
{
   return a+b;
}

float add(float a, float b)
{
   return a+b;
}


Naming decoration aka Name mangling :

Why?
In early days, C++ compilers used to convert C++ source into C code.
C does not support two functions with same names, hence names have to be decorated in order to conform them to 'C' identifier rules.
Even after development of compilers that can translate C++ source to machine code or assembly directly, system linkers did not support C++ symbols. So mangling still required.

The C++ language does not define a standard decoration scheme, so each compiler uses its own.


For following compiler mangling details are below:
g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5

For void add(int,int) Mangled name is _Z3addii
For void add(float,float) Mangled name is _Z3addff

In g++ generally,
All mangled symbols begin with _Z (note that an underscore followed by a capital is a reserved identifier in C and C++).
For nested names (including both namespaces and classes), this is followed by N. Then a series of pairs (the length being the length of the next identifier), and finally E. For example, 

namespace Earth
{
    class Man
    {
        void Born(float);
    }
}

The name Born is mangled as
_ZN5Earth3Man4BornEf
_Z        : mandatory
N         : says that namespace/class follows
5Earth : 5 characters in following dentifier "Earth"
3Man   : 3 characters in Man
4Born  : 4 characters in Born
E          : End of name
f           : Parameter is float

Only parameterized CTOR: Demo (along with error by g++)

#include <iostream>
using namespace std;

class SI
{
   float pple;
   float rate;
   float n;

   public:
     //
     // We have written only parameterized CTOR
     // In this case, C++ DOES NOT PROVIDE US WITH
     // default constructor.
     //
     SI(float rate, float n)
     {
        this->rate = rate;
        this->n = n;
     }
      void SetInput(float pple);
      void SetInput(float pple, float n, float r);
      float  CalculateSI();
};

void SI::SetInput(float pple)
{
   this->pple = pple;
}
void SI::SetInput(float pple, float n, float rate)
{
    this->pple = pple;
    this->rate = rate;
    this->n = n;
}

float SI::CalculateSI()
{
  return (pple *rate * n) /100;
}

int main()
{
  SI s1;
  s1.SetInput( 1000);
  s1.SetInput(1000, 6.7, 4);
 cout << endl <<"\t Simple intereset = "<< s1.CalculateSI()<< endl;

  return 0;
}
/*
ctor_only_param.cpp:44: error: no matching function for call to ‘SI::SI()’
ctor_only_param.cpp:16: note: candidates are: SI::SI(float, float)
ctor_only_param.cpp:5: note:                 SI::SI(const SI&)
*/

Parameterized constructor Demo

#include <iostream>
using namespace std;

class SI
{
   float pple;
   float rate;
   float n;

   public:
      SI()// This is default constructor
      {
         rate = 10;
         n = 3;
      }

      SI(float rate, float n)// This is parameterized constructor
      {
         this->rate = rate;
         this->n = n;
      }

      void SetInput(float pple);
      void SetInput(float pple, float n, float r);
      float  CalculateSI();
};

void SI::SetInput(float pple)
{
   this->pple = pple;
}
void SI::SetInput(float pple, float n, float rate)
{
    this->pple = pple;
    this->rate = rate;
    this->n = n;
}

float SI::CalculateSI()
{
  return (pple *rate * n) /100;
}

int main()
{
  SI s1;

  s1.SetInput( 1000);
  s1.SetInput(1000, 6.7, 4);
    cout << endl << "\t Simple intereset = "<< s1.CalculateSI()<< endl;
 
  SI s2(9.5, 5);
  s2.SetInput(5000);
  cout << "Simple interest = "<< s2.CalculateSI() << endl;

  return 0;
}


Saturday, December 17, 2011

Compilation Process (C and C++ particular)


Compilation starts with preprocessor. Preprocessor expands our source code and often writes it into intermediate file.

There are two passes in compilation:
First pass parses pre-processed code i.e. breaks code into small units. For example if statement is “A+B” then elements are ‘A’,’+’,’B’. Global optimizer is used between first and second pass to produce smaller and faster code.

In second pass, code generator walks through parse tree, which is generated in first pass, and generates either assembly language code or machine code for nodes of tree.
For assembly code assembler should run.

Ultimate result of both cases is an object module (.o or .obj) (.o file generated here is different than finally generated a.out file)

Peephole optimizer used in second pass to look for redundant assembly language statement.

The linker combines a list of object modules into an executable program that and run by OS
Linker is useful when function of one object module makes reference to function or variable in another object module. These references are resolved by linker. Linker takes help of libraries to resolve these references.

Compiler performs type checking during first pass. As this type checking occurs during compile time, this is called as static type checking.

[Courtesy : Rajesh Deshpande]

Tuesday, December 13, 2011

Constructor and destructor

If baby takes birth and dies away immediately, then the "baby" (who belonged to MAN class) has performed two functions: "being born" and "dieing". Similarly there are TWO mercy functions for ANY C++ object:
1. constructor: After allocation of memory, initializes it.
and
2. destructor: Before deallocation of memory, de-initializes it.

Constructor gets called automatically when an object is created. and
destructor gets called automatically when an object is about to die (go out of scope).

#include <iostream>

using namespace std;

class Man
{
   float height;
   float weight;

public:
   Man()
   {
     cout << "Man born" << endl;
   }

   ~Man()
   {
      cout << "Man died" << endl;
   }
};

int main()
{
  Man Hritik;
  return 0;
}

Thursday, December 8, 2011

Function with default arguments: Demo

#include 
using namespace std;

class SI
{
   float pple;
   float rate;
   float n;

   public:
      // Function with default arguments. (must be from right to left)
      void SetInput(float , float n = 3, float rate = 10);

      float  CalculateSI();
};


//
//   setInput: Function definition 
//   You may not write default argument values in definition
//
void SI::SetInput(float pple, float n, float rate)
{

//   This line is to test whether this contains address of caller object or not
//   cout << "this : <"<< this << ">"<< endl;

//
//  "this" is necessary here to resolve ambiguity,
//  Our class has the data members pple, rate, n and
//  we have the very same names as the parameters to this function
//
    this->pple = pple;
    this->rate = rate;
    this->n = n;
}

float SI::CalculateSI()
{
  return (pple *rate * n) /100;
}

int main()
{
  SI s1;
  s1.SetInput(1000,1);
  cout << endl << "\t Simple intereset = "<< s1.CalculateSI()<< endl;

//  This is to test whether "this" contains address of the caller object or not.
//  cout << "Address of s1 : <"<< &s1 << ">" << endl;

  SI s2;
  s2.SetInput(2000,4);
  cout << endl << "\t Simple intereset = "<< s2.CalculateSI()<< endl;

  SI s3;
  s3.SetInput(5000,3.5);
  cout << endl << "\t Simple intereset = "<< s3.CalculateSI()<< endl;

  SI s4;
  s4.SetInput(4538,9.32,5.7);
  cout << endl << "\t Simple intereset = "<< s4.CalculateSI()<< endl;

  SI s5;
  s5.SetInput(5000);
  cout << endl << "\t Simple intereset = "<< s5.CalculateSI()<< endl;

  return 0;
}

Reference variable : Classical function "swap" demo

#include<iostream>
using namespace std;

void swap(int &a, int& b)//'&'indicates call by reference
{
   int temp = a;
   a = b; // a and b are reference variables
   b = temp;
}
main()
{
   int x =10 ; // initialization
   int y =20 ;
   cout << "\nx = " << x << "   and y = " << y;
   swap(x,y);//call
   cout << "\nx = " << x << "   and y = " << y;
}

Reference variable : Demo

//reference.cpp

#include<iostream>

//Syntax of reference variable
//data_type & reference_name = variable_name;

using namespace std;
main()
{
 int x ;
 x = 10;
 int &y = x; // reference MUST always be initialized at declaration
 cout << "\nx = " << x << "   and y = " << y;
 y = 5;
 cout << "\nx = " << x << "   and y = " << y;
 x = 15;
 cout << "\nx = " << x << "   and y = " << y;
}

//Description:
//Lvalue : Location (address) of an expression
//Rvalue : VAlue of expression
//e.g. -
//  int a,b;
//a=4;  // Rvalue 4 is stored in Lvalue of a
// b = a;//Ralue of a is stored in Lvalue o fb



Think of REFERENCE variable as a constant pointer that is deREFERENCEd each time it is used!

Wednesday, December 7, 2011

Basic encapsulation (Accessing data through functions) Demo

//person_class.cpp

#include<iostream>
#include<string.h>
using namespace std;

class person
{
   // data members
   char name[30];  // Default access specifier is private
  int age;
  public:
   void getdata(void); //method declaration
  void display(void)//method declaration and definition
  {
  cout << endl <<"\t" << name ;
  cout << endl <<"\t" << age ;
  cout << endl <<"\t" << pid ;
  }
  private:
   int pid;
   public: void setdata(char[],int,int);
};

void person::getdata(void)
{
  cout <<"Enter name : ";
  cin>> name;
  cout <<"Enter age : ";
  cin>> age;
  cout <<"Enter pid : ";
  cin>> pid;
}

void person::setdata(char n[],int a,int p)
{
   strcpy(name,n);
   age = a;
   pid = p;
}
main()
{
   person raj,yash;
   raj.setdata((char*)"raj",20,101);

   yash.getdata();

   raj.display();
   yash.display();

   return 0;
}

Scope Resolution Operator Demo

//scope_resolution.cpp

#include<iostream>
using namespace std;

int m =10 ; //global variable

main()
{
      int m =20;

 { //starting the block
  int k = m;
  int m = 30;
   cout << endl << " m = " << m;
   cout << endl << " k = " << k; 
   cout << endl << " ::m = " << ::m;
 }//ending the block

 cout << endl << " m = " << m;
 cout << endl << " ::m = " << ::m;
}

Not using namespace std! Demo

#include<iostream>

//using namespace std;


// :: is scope resolution operator

int main()
{
  int a,b;
  std::cout<<"Enter two numbers : ";
  std::cin >> a >> b;

  std::cout << endl <<"Sum of " << a <<" and "<< b <<" is "<< a+b;

  return 0;
}

Tuesday, December 6, 2011

Procedure Oriented Programming: Example

//cshapes.h

#define T_CIRCLE 1
#define T_RECTANGLE 2
#define T_TRIANGLE 3

typedef struct CIRCLE_SHAPE
{
   short type;
   double x,y;
   double radius;

} CIRCLE_SHAPE;

typedef struct RECTANGLE_SHAPE
{
   short type;
   double x1,y1;
   double x2,y2;

} RECTANGLE_SHAPE;

typedef struct TRIANGLE_SHAPE
{
   short type;
   double x1,y1;
   double x2,y2;
   double x3,y3;

} TRIANGLE_SHAPE;

typedef union SHAPE
{
  short type;
  CIRCLE_SHAPE circle;
  RECTANGLE_SHAPE rectangle;
  TRIANGLE_SHAPE triangle;
} SHAPE;

double compute_area(SHAPE *pShape);
void draw_shape(SHAPE *pShape);


//cshapes.c
#include<stdio.h>
#include"cshapes.h" 
#include<math.h>


double compute_area(SHAPE *pShape)
{
   double area;

   switch(pShape->type)
   {
      case T_CIRCLE:
      {
         area = M_PI *pShape->circle.radius * pShape->circle.radius;
         break;
      }

      case T_RECTANGLE:
      {
         area = fabs(
    (pShape->rectangle.x2 - pShape->rectangle.x1) *
    (pShape->rectangle.y2 - pShape->rectangle.y1) 
      );
  break;
      }

      case T_TRIANGLE:
      {
        //double d1,d2,d3;
 // Hero's formula
 //d1 = (pShape->triangle.x1)
         area = 0.5; //TODO:
         break;
      }

      default: printf("Unknown shape\n");
   }

   return area;
}

void draw_shape(SHAPE *pShape)
{
   printf("Draw: ");
   switch(pShape->type)
   {
      case T_CIRCLE:
      {
         printf("Circle of radius %f at (%f,%f)\n", pShape->circle.radius, pShape->circle.x,pShape->circle.y);
         break;
      }

      case T_RECTANGLE:
      {
         printf("Rectangle with corners:  (%f, %f)and (%f,%f)\n", pShape->rectangle.x1, pShape->rectangle.y1,pShape->rectangle.x2, pShape->rectangle.y2);
  break;
      }

      case T_TRIANGLE:
      {
 printf("Triangle with coordinate: (%f,%f)", pShape->triangle.x1, pShape->triangle.y1);
      break;
      }

      default:
      printf("Unknown shape in draw!\n");
   }
}


//main.c
#include<stdio.h>
#include "cshapes.h"


int main()
{
  int i;
  SHAPE s[3];

  s[0].type = T_RECTANGLE;
  s[0].rectangle.x1 = 80.0;
  s[0].rectangle.y1 = 30.0;
  s[0].rectangle.x2 = 120.0;
  s[0].rectangle.y2 = 50.0;

  s[1].type = T_CIRCLE;
  s[1].circle.x = 200.0;
  s[1].circle.y = 100.0;
  s[1].circle.radius = 50.0;

  s[2].type = T_TRIANGLE;
  s[2].triangle.x1 = 4.0;
  s[2].triangle.y1 = 4.0;
  s[2].triangle.x2 = 4.0;
  s[2].triangle.y2 = 4.0;
  s[2].triangle.x3 = 4.0;
  s[2].triangle.y3 = 4.0;


  for (i = 0; i < 3; ++i)
 printf("Areas of shape[%d] = %f\n", i, compute_area(&s[i]));

  for (i = 0; i < 3; ++i)
    draw_shape(&s[i]);

  return 0;
}



How to run the program?

$gcc -lm -c cshapes.c -o cshapes.o
$gcc cshapes.o main.c -o shapes
$./shapes
Foot Note:
-lm links math library.
-c compile only option to generate object file.

HelloWorld.cpp

#include <iostream>

using namespace std;

// This is C++ comment


int main()
{
  int a,b,c;
  // cout is object of ostream class
  cout << "Hello World from C++ ";
  return 0;
}
// Description :
//cout is PREDEFINED object that represents
//standard output stream in C++.
//Here standard output stream is SCREEN.

//The operator << is called "INSERTION" operator or
//"PUT TO" operator.
//It sends (or inserts) contents of variable
//on its right side to the object on its 
// left.