Wednesday 30 March 2016

Preprocessor Directives: C++

Pre-processor directives may not be a popular part of the language but they sure are very important and useful. Here are some of their uses, these are not in any particular order.

Each Pre-processor directive must be in its own line. This means that you cannot as is the case with semi colon separated statements of the language, squeeze two or more pre-processor directives in one line. For example the following would not work:

#include <stdio.h> #include <stdlib.h>

Here are some of these directives in some useful depth:

#define :

The #define directive defines two things, an identifier and a character sequence. The identifier is to be used in the subsequent program just like a normal variable. And the character sequence is in fact the value of this identifier. So when the program will run, it is this character sequence that will participate in all the expressions where the identifier has been used. To be a little more exact and differentiate an identifier from the one defined using this pre-processor directive is the name for this, a macro
The syntax is very intuitive:
#define LENGTH 20

Notice that there is no semicolon in this statement. There may be any number of spaces between the identifier and the character sequence, but once the character sequence begins, it is terminated only by a newline.
Once a macro name has been defined, it may be used as part of the definition of other macro names. For example, this code defines the values of ONE, TWO, and THREE:

#define ONE 1

#define TWO ONE+ONE
#define THREE ONE+TWO
Macro substitution is simply the replacement of an identifier by the character sequence associated with it. Therefore, if you wish to define a standard error message, you might write something like this:

#define E_MS "standard error on input\n"

/* ... */
printf(E_MS);
If the character sequence is longer than one line, you may continue it on the next by placing a backslash at the end of the line, as shown here:

#define LONG_STRING "this is a very long \

string that is used as an example"
All of the stuff defined above is how you would invoke the described functionality in C. But in C++, this is not the only way to do stuff like this. The Const keyword has been introduced specially in C++ to define such macros.
The #define directive has another powerful feature: the macro name can have arguments. Each time the macro name is encountered, the arguments used in its definition are replaced by the actual arguments found in the program. This form of a macro is called a function-like macro. Example :

#define ABC(a) (a)>0?1:-1

The parenthesis ensure proper substitution and better results.
And now to somewhat repeat a pattern within the article, the text immediately above represent the only wau to define and use macros in C. But this is not so in C++. The inline keyword is used to define functions like this that are not called like a normal function but there is copied and placed upon the statement in which they are invoked.

#if #elif:

The following code snippets serve enough explanation togethor with the syntax for the #if and #elif directives.

#if expression
statement(s)
#elif expression
statement(s)
.
.
.
#endif
The #endif at the end may seem abnormal but it is what it is. 

#else :
The #if directive apart from being used with the #elif directive can also be used with the #else directive.
#if expression
statements
#else
statements
#endif

#endif :

As you have already seen, this directive is used with #if, #else, and the #elif directives. It doesn't really have any statements to follow it. It simply signifies the end of a conditional macro.

#error :

The #error directive forces the compiler to stop compilation. It is used primarily for debugging. The general form of the #error directive is:

#error error-message
The error-message is not between double quotes. When the #error directive is encountered, the error message is displayed, possibly along with other information defined by the compiler. It stops the compiler to even run the program.

At this point after understanding some of these conditional directives, one may ask why do we even need them? There question is valid and indeed a good one since we already have a simple, flexible and powerful if else system in our language for such type of decision making. Well the only difference between the two ways of doing apparently the same thing is amount of code that needs compilation. If we use the if() and else() blocks like most would do, then regardless of which condition is true, every block must be compiled. This means that the compiler must scan, parse and process each statement even though it is not be run considering the expression triggering them are false. This of course is fine for smaller or even bigger programs. But when there are performance issues then this may not be the optimal way of doing things. Compilation takes time. After all how fast can fast be. So if even the tiniest of times count, then it is best to use #if and #else directives. This is so because using pre-processor directives ensures that only those statement (in this case directives) are considered and compiled by the compiler that fall under the category of expressions turning out to be true. So if any expression is going to be false (this of course will be determined by the arguments being passed) then the statements in that block will be bluntly ignored by the compiler for that particular run of the source code. 
This is a big advantage when writing code for big projects. In fact I've seen from experience how heavily these pre-processor directives are used in bigger projects, projects seemingly out of my comprehension. 
#ifdef :
This is like a combination of if and define directives, obvious I guess. Consider the following code:
#ifdef macro_name
statements
#endif
The code b/w #ifdef and #endif will be compiled only if the macro name has been previously defined using the #define directive. This may seem to be a bit of a stretch in terms of it being of a very specific use. In fact that is the case. For all I care this is a short hand for doing something which could otherwise be done with a little more effort.
Consider the following macro definition using the #define directive:
#define HEY

Then accordingly the following directive is true and hence the 
enclosed statements will run:
#ifdef HEY
statements
#endif

The longer of doing this by using the #if directive and the defined
keyword (if you will).
The following is an expression, so it can either be true or false.
defined HEY
Of course it will be true if the identifier HEY has been defined
previously using the #define directive. And it will be false otherwise.
Since this is an expression, it will go rather nicely with our very own
#if directive as:
#if defined HEY
statements
#endif

The above expression: defined HEY can also be proceeded  with a '!' to negate the expression.

Again as a shorthand to using the ! before the expression, following directive can be used:
#ifndef HEY 
statements
#endif
So to state the obvious, the code b/w #ifndef and #endif will be compiled only if the macro name has NOT been previously defined using the #define directive.

#include:
The #include directive instructs the compiler to read another source file in addition to the one that contains the #include directive. The name of the additional source file must be enclosed between double quotes or angle brackets. For example,
#include "stdio.h"
#include <stdio.h>
The angular brackets are for the libraries already known to your compiler. Basically you have nothing to do with these except for using them.
The double quotes are for header files written by you, the creative programmer. 

#undef :
Enough construction for now, let's destroy something. Well to be fair I'll just be undoing something. As the name suggests, this directive un-defines a macro (for lack of a better word).
#undef macro_name
Before we move to the following directives, we need to know about two identifiers that are predefined. So they are just there, you just have to use them. And if you want to use them, you better get to know them first. Let's have the introductions:
__LINE__ is an identifier storing the line number or serial number of the currently compiled line of code.
__FILE__ is an identifier storing the name of the file being compiled.

And now for the useful part, here is how you ought to use these:
#line:

This directive is used to change the value of the two identifiers described
above. Here is how:
#line number "filename"
The number is any positive number that will become the new value of __LINE__ and the "filename" is optional and it is any valid file identifier which becomes the new value of __FILE__.
This does not change the order of compilation, it just changes the value of an identifier which contains the information of the line which is being compiled currently.

There are a couple of operators that go with these pre-processor directives:

# Operator:
The # operator is an entirely different thing from the pound sign used in all the directives. Firstly it works on the arguments passed to the directive. Its function is to convert whatever is passed to it into a string. 
#define convrt(a) #a
In the above example, the argument a is being fed to the # operator which will convert a into a string. And this string will returned by the directive when called upon.
So when the following line of code is written following the above directive:
cout<<convrt(hey i am 007);
It equates to the following:
cout<<"hey i am 007";

## Operator":

The ## operator concatenates. But beware, it is very different from your daily normal use string concatenation. ## operator literally concatenates things to give a name of an identifier. To see what I mean, consider the following:
#define concat(a, b) a##b
So whenever concat is called with two parameters (each being a collection of characters), the macro will return another collection of characters which is the concatenation of the parameters. This returned value can in fact be used as an identifier. So if we have an identifier with a big name like: Sum_Of_Numbers:
int Sum_Of_Numbers=5;
And now think you need to print the value of this variable. The obvious (or sane) way of doing this would be:
cout<<Sum_Of_Numbers;
But no, we must use cryptic code else how will people be impressed. Following shows how we would do this using our parameterized directive:
cout<<concat(Sum_Of, _Numbers);
The derivative will return a concatenated string of character (not the data type string) and this returned value will be placed over the calling statement. Hence the above statement will literally change to the following:
cout<<Sum_Of_Numbers;
Which is what we wanted to do in the first place.
Too many ingredients for a simple recipe. 

Predefined Stuff in Macros:
Along the lines of __LINE__ (see what I did there?) and __FILE__,
There are some more of these predefined identifier things. Some of
them are:

__DATE__:

This one contains a string of the form month/day/year that is the date
of the translation of the source of file into object code.

__TIME__:

This one contains the time at which the program was compiled. The
time is contained in a string of the form: hour:minute:second.

__STDC__:

The meaning of __STDC__ is implementation defined (to be honest 
I don't really know what that means). Generally, if __STDC__ is defined,
the compiler will accept only standard C/C++ code that does not contain
any nonstandard extensions (don't really know what that means either).

__cplusplus:
This one contains a value. It can be any value. The important thing is the number of digits in the value contained. If the number of digits is 6 it means that the compiler is conforming to Standard C++. For digits less than 6, you have nonconforming compilers in hand. 

Pointer Concepts in C/C++

Pointers, a very apt name considering they sting a bit or a lot depending on how many of them are there. 
I am assuming that the reader is familiar with pointers to the extent of simply understanding what they mean. From here in out we'll be looking into different ways and places where pointers can be used and how they are to be used. After all we don't want any injuries, do we?
Let's get on with it then, the basic syntax for defining a pointer is as follows:
type *name;
Where type is what we call as the base type. The base type of the pointer defines what type of variable the pointer can point to.
Technically, any type of pointer can point anywhere in memory. However that can be problematic when it comes to pointer arithmetic. You see pointer arithmetic is done relative to the base type, so it is important to declare the pointer correctly. 


Making pointers point to variables of types different then the base type of the pointer:

As I said before, a pointer cares about holding an address, and all addresses in memory are the same to it. It doesn't really care what data type is stored at the address. The base type only restricts the number of memory addresses one pointer can refer to at once. So if we have a pointer of type int, then that only means that this pointer will point to 4 memory addresses at once (4 being the number of memory addresses required by an int). So to this pointer, we give an address and it automatically assumes that this address and the consecutive three addresses after that, are the ones it is supposed to point to. All we have to do is give pointer a starting address and then some how make sure that the pointer is not fed with more addresses then it can handle by definition. Hence we can make an int pointer point to a double variable by using type casting (making sure the pointer gets exactly what it can handle):
double x;
int *p;
p=(int *)&x; //p=(int sized)starting address of something.

Multiple Indirections (pointers to pointers):

It's like keeping a key for a lock that contains another key which in turn opens the lock where the actual cash is. But you probably knew that already. Following is the syntax:
type **name;
The double asterisk is not only necessary while declaring a pointer to a pointer but is also necessary when extracting values using these doubly indirected pointers.


int x, *p, **q; //x is an integer. p is a pointer to an integer. q is a pointer to a pointer to an integer.

x=10;
p=&x;
q=&p;
Now accessing x can be done using any of the following three ways:
x //equals 10
*p //equals 10
**q //equals 10


Initializing Pointers:

Pointers are supposed to carry addresses and they will carry addresses. Now whether these addresses mean anything or not is another issue. You can either give an address to a pointer (that's what you should do) or you can let the compiler give the pointer some meaningless value (to keep it worm). Global and static local pointers are automatically initialized to null, other pointers are given unknown, random values. Of course this assignment of NULL value can be done by you as well:
type *p=NULL or 0;

Pointer Arithmetic:
Pointer arithmetic is what distinguishes C/C++ from most languages like Java and Python. These languages only go as far as dealing with objects and variables by passing their addresses around. C/C++ goes the extra mile. And mind you it's a very long mile (wait, that can't be right, a mile is a mile, there is no such thing as a long mile, all miles are the same length). Anyway, pointer arithmetic is like a luxury meaning that you can live without it but if you have a good handle over it then that means you deserve some intense reverence. 
As the name suggests, pointer arithmetic means adding and subtracting pointers together to create magic. I find it important from a reader's perspective. If I am given the task of reading and then figuring out some one's else's code in C, then that most likely means that code has the worth of being considered by someone other than the creator. And if that code has such worth then it most likely is filled with a lot of pointer arithmetic. 
Let their be a pointer p of data type int, then we are allowed to perform only addition and subtraction operations on it and those too are governed by the following rule:
p can be added to or subtracted from anything which is a multiple of the size of int (the base type).
We can increment p, decrement p, add some number to p, subtract sum number from p.
We can subtract two pointers only. This is because subtracting a pointer from a number does not make any sense. The vice-versa is quite possible though.
Adding two pointers is no problem.
We can apply relational tests to pointers. Eg. p<q will be true if p points to a lower address then q.

Array of Pointers:
Just like with any other data type we can have a whole array full of pointers. The purpose is still the same, pointing at a lot more than one thing but without having to name each pointer separately. To have 10 pointers with the similar name :
int *p[10];
Now to make the ith element of the above array to point to some variable do :
p[i]=&variable;

Pointers to Arrays:
This time there is one pointer that will point to a whole array. Remember a pointer can point to any thing but it's the base type that limits how many addresses the pointer can control at one time. This principle is used when pointing to arrays using pointers.
Suppose an array int A[10];
Now we want the address of the first element of this array, its easy right?
&first_element : &A[0] 
But C++ has a shorter way to do the same thing:
&A[0] means the same as A (That's right. The name of the array alone, without any brackets). Now we can have a pointer point to the first element of the array using:
int *p;
p=A ; //instead of p=&A[0]
Now keeping the above code in mind, think about how you would access elements of the array? Here is how:
A[3] is the same as *(p+3); 
This works like this: p is a pointer containing an address and adding 3 to p means jump three addresses ahead of the address specified by p it self and the * means that get the value stored at that address is being referred to. Hence it means the same as A[3].
This very concept can be extended to multidimensional arrays as well. So again assume : 
int *p,arr[m][n];
p=arr; //same as p=&arr[0][0]
Now accessing certain element of arr means jumping to it from the first address, so arr[i][j] can be accessed like:
*(p+no. of address units to jump to get to the element);
This changes to:
*(p+i(total no. of columns)+j)==*(p+i.n+j); 
But there is one little change, to make the pointer arithmetic work properly we have to add another thing: (type*), so a[i][j] is actually equal to *((int*)a+i.n+j). ALWAYS ADD THE (int*) in the beginning. It is important. This is basically an cast that converts a two dimensional array into an int pointer type. Check out the following to understand better:
int a[10][10];
int *p;
Unlike in normal array cases, we cant do p=a; This will produce an type cast error. We can't convert an int to an int* type so we have the cast the int into an int* as:
p=(int*)a;
Similarly for a two dimensional array we can use a pointer to reduce it into a one dimensional array as:
int a[10][10],*p;
p=(int*)&a[1][]; 
This means that p now points to the first row of a. Hence p+i will point to the ith element of the array at the 1st position in a (remember a is an array of arrays).
We can excess each element as *(p+i) and then to point to the next array all we have to do is p=p+(index*row_length) and p will then point to the array at the index specified.



Passing arrays as an argument to functions:

It is not possible to pass an entire one dimensional array as an argument to a function in c++. But the same effect can be achieved by being creative in a number of ways. First thing first, we have to prepare a function while defining it in such a way that it is ready to receive an array as its argument. So we play with the parameters of the function in the following 3 ways:
1) int func(int arr[10]){...}
2) int func(int arr[]){...}
3) int func(int *p){...}
In all the above cases the function func() now accepts an address to the first element of an int array (to be more precise though, our function can work with any address as its argument). Now let us give our function some address as its argument:
func("some address"); 
Now based on this the function will react in three different ways depending on its declaration.
1) If the function was declared in this fashion, the address passed as the argument will be the address of the first element of the int array of size 10 and can be used inside the function body.
2) The address is now the address of the  first element of this un-sized array.
3)The address is passed on to this pointer p. p now points to this address and hence can be used in any way a normal pointer could be used, but for our purpose we can use it to manipulate an array.

Now imagine an array int haha[10]. Simply do the following to pass this array as an argument to our function:
func(haha);
Remember we are just passing an address to our function (haha means &haha[0]). Hence the changes made by the function will reflect in the original array it self.
When a two-dimensional array is used as an argument to a function, only a pointer to the first element is actually passed. However, the parameter receiving a two-dimensional array must define at least the size of the rightmost dimension. (You can specify the left dimension if you like, but it is not necessary.) The rightmost dimension is needed because the compiler must know the length of each row if it is to index the array correctly. For example, a function that receives a two-dimensional integer array with dimensions 10,10 is declared like this:
int func(int arr[][10]){...};
Similarly When passing multidimensional arrays into functions, you must declare all but the leftmost dimension in the parameter list of the function.


Pointers to Functions:
I know what you are thinking. A pointer points to a variable, big or small. Since when have they started pointing to functions as well? But remember the only thing that a pointer does is point to something in memory. All it cares about is an address to start with and a limit to how many addresses following the starting one is it supposed to handle at a time. Consider a function:

int add(...)
{}
This function too has an address in memory which can be pointed to by a pointer. Just like in an array the name of the function 'add' alone is actually a shorthand of specifying the starting address of the memory block which defines this function. So we can use the following two things interchangeably:
add means &add(...)
The pointer pointing to a function must have the same type as the return type of the function it is pointing to. But unlike the normal pointer declaration, we have to specify the number and type of arguments the function to be pointed is expected to have. So for example if we have to declare a pointer which points to the following function:
int add(int a, int b);
We will doing something like this:
int (*p)(int,int);
The above statement means that the pointer p points to a function that returns an int value and has two arguments both being int in this case. Basically it tells the compiler to reserve that much space so as to occupy the function arguments as well for the pointer so that it can store and use these arguments.
Now our pointer p is ready to point to the add function:
p=add; // evaluates the same as this illegal but meaningful statement : p=&aff(int,int);
The main use of this tool is to pass a function as an argument to another function. The function which is expected to have a pointer to another function as its argument should be defined in a special manner. For example :
int big_function(int a,int (*ptr)(int,int));
This means that this function is expecting a pointer which points to a function returning an int and having two int arguments. 
big_function can use ptr like this:
int big_function(int a,int (*ptr)(int,int))
{
return a+(*ptr)(2,3); // Basicaly add(2,3) can be called as                  (*ptr)(2,3) assuming that ptr points to add following the                    manner explained above.
}
Remember, its the calling function's duty to give actual values as arguments to our pointed function inside its (calling function's) body.
The use of () around *ptr when calling the function it points to is not necessary but is popular as it directly tells that a function has been called using a pointer. Another simpler syntax of doing the same thing inside the calling function would be:
ptr(2,3); 
But this can sometimes confuse us as we might think that we are calling a function named ptr but actually we are not. So instead of "return a+(*ptr)(2,3);"
We could also have used 
"return a+ptr(2,3);"
Another thing to consider is that we could have eliminated the use of a pointer completely in the first place in the above example by calling the big_function as: 
big_function(3,add);
The declaration of the big_function of course will remain the same.
This whole concept can be used as an alternative to switch statements where for every different case we call different function like in a calculator program. Using this we can simply create an array of function pointers and call the required function by altering the index of the array.
Overloaded functions can also assigned to a pointer. Care should be taken as to how the pointer is defined argument wise so as to be clear on which overloaded version of a function is the pointer is supposed to point to.
Pointer to Objects of Classes/ Structures:
These things are relentless, like zombies. There is hardly anything in the language to which a pointer can't point to. You don't believe me? Consider this then:
class abc
{};
abc is a nice and healthy class, sitting there waiting to be instantiated. 
abc obj; //instantiated
obj.member(); //good old member call using an object
I wonder what is wrong with this? Seems perfectly fine and potent to me. But no, we must use pointers somehow. Otherwise whats the point. Firstly we declare a pointer of the base type abc:
abc *ptr;
So far it does not point to anything. Hungry pointers (like zombies) are not a good thing. We must keep them fed and occupied. So let's create a new object dynamically and feed it our zomby. 
ptr=new abc();
Now calling a member can be done like:
(*ptr).member();
There is shorthand for this though (of course there is)
ptr->member();
So :
(*ptr).member()  is the same as ptr->member();
The same can done with the members of a structure.
I would like to give a little insight on why do we need this. Why can't  we use the more clean way of dealing with objects, you know, the one involving no pointers. The answer is: "Dynamically created Objects". Sometimes one doesn't know how many objects of a class are needed by the program to do its job. In those cases, objects are created and destroyed dynamically. This is done easily enough using the new and delete operators. The problem is that we can't name these objects before hand because we don't know how many of them are going to be there in our program. And if we can't name them, how can we write code that uses them? This is where pointers come to our rescue. It doesn't matter if an object has a name or not, it will surely have an address. And all we need to do then is to keep a pointer ready to point to the address of this dynamically created object. And using this pointer then, we can put our object to work. And since one pointer can be used to point to more than one thing (one at a time of course), we are free to use this  pointer with as many dynamically created objects as we like.

The this pointer:
Refer to the article on this link:this link
Pointers to derived types:
Assume A is the base class and B is derived from A. A pointer of type A* can point to an object of class B. This is an important exception to the rule that pointers of one type can not point to objects of other types. The reverse is not possible though. The important thing to know is that the pointer of the base class can be used to access only those members of the derived class that were inherited from the Base class.
class A
{
int i;
};
class B: pubilc A
{
int j;
};
Now,
A *p;
B obj;
p=&obj;
p->i // will work
p->j //will not work
In order to gain full access to the members of the derived class via the pointer of the base class, we can cast the base class pointer into a derived class pointer type.
((B *)p)->j //now this will work.
You should not however, try and increment a base class pointer, because it will then not point to the next derived class object. The pointer arithmetic will be in accordance to the base class, hence this will cause problems.
The above concepts are used for run time polymorphism using virtual functions.


Pointers to class members:
We have assigned regular pointers to objects of class. And using these pointers and the arrow operator we were able to access the members of objects. But in C++, there is a special pointer, which points only to a class member and not to any object of that class. This type of pointer is called pointer-to-class. Since this pointer is all together different from the regular pointer, it has to be given a separate set of operators to work with as well. '.' is replaced by '.*' and '->' is replaced by '->*'.
Suppose an object of size 50, starts at address 300. Suppose that a member of this object is at the 20th position in the whole object space. pointer-to-member takes advantage of this little offset knowledge to access the members alone of the object. So basically, the ptm will now point to the address 300+20, in order to access the desired member.
Consider:
class A
{
public:
int i;
A(int x) {i=x;}
int doubleIt()
{
return 2*i;
}
};
Declaring a ptm for the member i in the class A:
int A::*p; 
int is there because p is intended for an integer, A:: is there because p is special pointer, it points to a member of class A. The member is not specified as of yet.
Setting an offset within the class for p:
p=&A::i;  
This tells that p is supposed to point to member i of any object of class type A.
Similarly:
int (A::*d)(); 
This is a pointer to a function, a member function. The () in the end separates the two: pointer to member and pointer to member function.
d=&A::doubleIt() //assigning a member to d.
The following code segments can hopefully draw out some guideline
on how to use these type of pointers:
A obj1(1), obj2(2);
cout<<obj1.*p   // will print 1
cout<<obj2.*p   //will print 2
cout<<(obj1.*d)() //will return 2
cout<<(obj2.*d)() //will return 4
So basically, we kind of have (not really though) created members of the class. Members that are pointers. Pointers to other fellow members. So, obj.*p means, access some member of obj (obj.) and *p means, the newly made member, the pointy one.
Now instead of having obj, we can have a pointer to obj. And then through this pointer we can access these pseudo members of obj.
A *ptr=obj;
cout<<ptr->*p // Easy isnt it?

Difference between regular Pointers and PTMs:
A obj;
int *p;
p=&obj.i; 
The above example has a regular pointer pointing to some int, in this case a member of an object. p can point to only this member of only this object. 
int A::*p;
p=&A::i;  
PTM, can point to the member i of any object of class A from now on wards.
Basically, regular pointers just contain a singular address, hence they will always point to only one thing. But PTMs contain offsets within an object, hence they can be used to point to members of any objects. Its like applying the offset to different objects.

All about functions in C++

Functions and mostly functions are enough to code the solution for any problem and that too very efficiently. I have the entire legacy of C language to back me up on this.
Starting off with a quick definition, functions are nothing but a name or a signature for a piece of code that can be used as many times as one likes by using the name/ signature and also passing some additional information (arguments) if need be.

A function must be declared, defined and used. Except the last bit (used) is optional.
Here is the general form of a function declaration and definition:
return type name(parameter list)
{
      body of the function.
}
I assume the reader is familiar with such basics of functions. Remember this article is intended for refreshing some very vital and some what in depth concepts about functions in C++. It does not actually contain everything there is to know about functions in C/C++. But I'll tell you this, if you stay with me throughout this article, you are assured a superior knowledge of functions then most students out there. Also the facts/ reasons are in no particular order:

A function can return any type of data except for an array. I guess that is a perfectly fine way of saying what I wanted to say. 

The parameter list, the one I mentioned in the general form of the function bit, is nothing but a comma separated list of the form: 
type name1, type name2, ......

As you might have noticed, the parameter looks a lot like a bunch of variable declarations (with strict and subtle differences of course). In fact you can sure think that way. It is a nice little analogy to draw in your mind when thinking about parameters and arguments. The analogy goes something like this:
The function defines variable inside its parameter list which catch the value of the arguments passed to it. These parameters are called Formal Parameters.
If the parameter is supposed to be empty then let it be empty. There is no need to write the keyword void  inside the parenthesis of the function declaration indicating the absence of any parameters for the function. In C++:
int func() and int func(void) are the same.

You can define a function in many places inside a program. Example, in a class, in a structure, etc. What you can't do is nest a function definition inside of another function definition. This is to say that you cannot define a function within a function.


Call by value and Call by reference:
Passing an argument to a function can be done in two principle ways. In call by value, the values of the variable passed as arguments to the function at the time of calling the function are copied and are pasted as the values of the formal parameters of the function. Hence the function is only able to affect the values of its formal parameters and the original variable passed as arguments are not affected. Basically, a copy of the variable is given as argument to work with, the original variable remains untouched and hence unaltered.
int twice(int a)
{
  return 2*a;
}
int main()
{
  int x=10;
twice(x);//This line baicially means a=x where a is the local                               variable inside the function twice.
}
In call by reference the function to be called does not expect actual values as its argument. It anticipated the addresses that holds the actual data. The function then goes on and makes changes at the address specified hence changing the actual variable's values.
int twice(int "A SPECIAL VARIABLE THAT CAN HOLD THE ADDRESS OF THE TYPE SPECIFIED" aka a) 
{
return 2*(*a); /*return the twice of the value at address stored at a.*/
}
int main()
{
int x=10;
twice(&x); /*here the address of x is passed as an address is expected by the function.*/
}

Now a (the special variable) has to be something that can hold an address :
1) a can be a pointer (as in C) twice(int *a);
2) a can be something that will explained later.


Returning from a function:
One can return from a function with or without a return value. Both of this can be done using either the return statement or by simply reaching the end of the function i.e. '}'.
In C++, if a function is specified as returning a value, any return statement within it must have a value associated with it. However, if execution reaches the end of a non-void function, then a garbage value is returned. Although this condition is not a syntax error, it is still a fundamental flaw and should be avoided.
If a function returns a value, it is not necessary to assign it to some variable. Because if a value returning function is called without using it in an expression or assignment, all of its functionality is executed and the return statement is ignored. So :
int prnt()
{
  cout<<"hey";
return 11;
}
int x=prnt() 
will assing 11 to x but after it has printed "hey" on the screen.

On the other hand, the following statement:
prnt(); 
will just print "hey" and return nothing to nobody.

Interestingly, 
cout<<prnt();
will print the following on the screen : "hey11".

Returning Pointers:
As I said a function can return anything, anything but an array. And as with most things, pointers have a way of being at the center of the action of this one as well. We can very well have a function whose return type is like that of a pointer. This of course means that the function will be returning an address. 
type * name(..)
{
....
return "Some Address";
}


Function Prototypes:
A function prototype is nothing but a function declaration without the body of the function i.e. the code inside of the curly braces and without the curly braces themselves. It looks like this:
int abc(...); 
Function prototype must occur before we call the function. And of course the definition of the function can follow even after function has been called and used.
Any standard library function used by your program must be prototyped. To accomplish this, you must include the appropriate header for each library function. All necessary headers are provided by the C/C++ compiler. In C, the library headers are (usually) files that use the .H extension. In C++, headers may be either separate files or built into the compiler itself. In either case, a header contains two main elements: 
1) Any definitions used by the library functions and 
2) The prototypes for the library functions.
Functions with variable length parameter list:
We are all taught this one fundamental rule, if the function has n number of parameters, we must pass it n number of arguments. Nothing less than n is acceptable (unless the concept of default parameters is used) and surely any number of arguments more than n will simple just make the compiler fire at you with abusive and hurtful error messages. 
Well as it turns out, we have a way of getting around the later part of the two prohibited situations described above. This means we can if we want to, define a function in such a way that it will work properly even if more arguments are passed to it then expected/ needed. A function that can have a variable number of arguments passed to it takes the following form:
int func(int a,int b, ...)
The the three dots are necessary syntax.
The above function must be called with at least two int arguments and after that it can have any number of (zero or more) arguments passed to it. The extra arguments are ignored completely by the compiler.
Any function that uses a variable number of parameters must have at least one actual parameter. For example, this is incorrect:
int func(...); /* illegal */
The point of this is that all other parameters are nameless and hence are unusable, so they will basically be ignored, its just to make sure that the function works correctly despite of any number of arguments we end up giving it.
Inline Functions:
In C++, you can create short functions that are not actually called; rather, their code is expanded in line at the point of each invocation. This process is similar to using a function-like macro. To cause a function to be expanded in line rather than called, precede its definition with the inline keyword.
inline int fn()
{
return 2;
}
int main()
{
return fn();
}
Like register (read about it in the keywords article), inline is a request not a command, the compiler can ignore this and can call the function as a normal functions. This happens when we make a recursive function into an inline function. The compiler does not make it inline it just ignores this request and uses this function as a normal one.

The use of ::
Sometimes we can run into situations where a function has a local variable with exactly the same name as that of a global variable (or variable of higher scope). In these cases, we can use the :: operator to differentiate a global variable from a local one. 
int i; // global i
void f()
{
int i; // local i
::i = 10; // now refers to global i
.
.
.
}
Function Overloading:
Function overloading is the process of having the same name for two (or more) different functions. The name of the two (or more) functions is same but the difference lies in the function body and the argument list. The return type of two overloaded functions can be different but that alone is not enough to differentiate two functions with the same name. Either the type or the number or both things or the parameters to the functions should be different.
The most important use of function overloading is overloading constructors:
Overloading a constructor is really easy, just have constructors with different parameters in them. Different here can be qualified by a different number of parameters and/or different type of at least one parameter.
Default Arguments:
What do we mean by a default value? It's a value provided in case nothing else is available. In the default arguments, a parameter of a function is given a default value. This default value can be over written if an argument is passed corresponding to the parameter. If no such argument is passed then this default value is considered.
int haha(int x=2) //2 is the default value
{}
haha(); // in this case 2 would be used.
haha(3); //in this case 2 would be used.

All the parameters with default values must be to the right of all the parameters with no default values.
int haha(int x, int y=2, int z) // this is wrong:
int haha(int x, int z, int y=2) /*this is correct, no default value less parameter should be to the right of a default valued parameter*/
This concept can be used as an alternative to overloading parameter-less constructors in a class.