C++ Pointers & References : Talks to you

# Introduction :-
    # For a C++ program, the memory of a computer is like a succession of memory cells, each one byte in size, and each with a unique address.
    # These single byte memory cells are ordered in a way that allows data representations larger than one byte to occupy memory cells that have consecutive addresses.
    # When a variable is declared, the memory needed to store it value is assigned a specific location in memory ( its memory address )
    # Operating system decides the memory locations/addresses where your C++ store its data if needed.
    # So that will be great if using C++ we can find out the memory address of particular variable at run-time in order to access data cells that are at a certain position relative to it.
    # This is where, Pointers comes in field.
    # of-course pointer is just like other variables in C++ that can store some data, but that matters what you are going to store, In case of pointers we are going to store memory addresses.
    # Pointer is a Special Kind Of C++ Variable that can store run-time memory addresses for a particular variable.

# Pointers in C++?
    # Pointers are C++ variables and are special because compiler knows some special rules about them.
    # Basically we are going to store memory address in a given pointer.

# Why use Pointers?
    # http://stackoverflow.com/questions/162941/why-use-pointers

# Address of Operator?
    # This Address of Operator ( & ) used to obtain the address of a variable.
    foo = &myvar;
    # I have a simple C++ variable named  myvar  and i want to obtain its run-time address.
    # NOTE:- they can also create a function for that but they create an operator for it because it is more handy then a function.
        # You can Imagine ( & ) Address-Of-Operator as a function if that helps you to understand more.
        foo = &myvar;
        foo = getAddress(myvar);
        # Both will do the same thing, both will return the address of variable 'myvar'
        # Do not confuse here, getAddress() is s user-defined function that do exactly same as what Address-Of-Operator do.
        # OK now we have a special variable named 'foo' , actually this is a pointer variable with a special tag that tells compiler, it is a pointer not a normal variable, now compiler knows how to deal with it.

# De-reference Operator in C++ ?
    # This De-reference Operator ( * ) used to obtain the contents of a Pointer/Memory address.
    baz = *foo;
    # get contents from  foo  Pointer Variable and copy them into variable  baz.
    baz = getContents(foo);
    # Again, here  getContents() is a user-defined function that do exactly same as what De-reference Operator does.

# How to Declare Pointers in C++?
    # Pointers are special C++ variables because they have different properties according to their corresponding type definition.
    # Declaration of Pointer
    type * name;

    declarePointer(type, name);
    # NOTE that, declarePointer() is a user-defined function that does exactly same as that Dereference-Operator when used with type and variable name.
    # So, actually  (  *  ) itself able to create Pointers and for obtaining their contents, this knows whether you want to define a pointer variable or you want to obtain Pointer contents.

    # Examples :-
    int * number;
    char * character;
    double * decimals;
    # We defined three Pointer variables with different data type they points to. But all of them are pointers and all of them are likely going to take same amount of memory ( the size in memory of a pointer depends on platform where the program runs.)
    # When you use De-reference Operator (  *  ), it know about the type of Pointer Variable and will read only those number of bytes that it occupy.
    # for example, if a Simple C++ Char variable takes 1bytes of memory space, then while we De-reference its pointer than we will only  get the content of 1bytes not more than that.

    # NOTE :-
    As in the case with most variables, unless you initialize a pointer it will contain a random value. You do not want a random memory
    address to be accessed so you initialize a pointer to  NULL.
    NULL  is a value that can be checked against and one that can not be a memory address.
    # Declaring a Pointer with NULL value :-
    PointedType * PointerVariableName = NULL;  // declaring pointer and initialize NULL value
    So, declaring a pointer to an integer would be:-
      int *pInteger = NULL;

    # For a type  T  , T*  is the type 'pointer to T'
      means, a variable of type  T*  can hold the address of an object of type T.
      char c = 'a';   // lets understand this as :-
        name: 'c',
        value: 'a',
        tags: {
          isPointer: false,
          type: 'char',
          address: '0x45ab78'

      char* p = &c;  // p  holds the address of variable c
        name: 'p',
        value: '0x45ab78',
        tags: {
          isPointer: true,
          isConstant: false,
          type: 'char',
          address: '0x9078bc'

      int* pi;   // pointer to int
      char** ppc;   // pointer to pointer to char
      int* ap[15];   // array of 15 pointers to ints
      int (*fp)(char*);   // pointer to a function, taking a  char*  argument; returning a  int
      int* f(char*);   // function taking a  char*  argument; returning a pointer to int
    # NOTE:- Why we need to declare a data type for pointer variable/normal variable?
      Every data type in C/C++ takes defined number of bytes in memory. for example:-  char  date type variable use 1byte of memory.
      what if we have memory address of a char variable, So we can say that => start from this memory address and read this number of bytes.
      In case of  int  variable, we need to read only 1 byte of memory from the pointer (memory address).

# Pointers as Function arguments :-
# Pointers of C++ Arrays ?
    # Arrays work very much like pointers to their first elements, and actually, an array can always be implicitly converted to the pointer of the proper type.
    int myarray [20];
    int * mypointer;

    # The following assignment operation would be valid
    mypointer = myarray;
        # mypointer  and  myarray would be equivalent and would have very similar properties. The main difference being that mypointer can be assigned a different address, whereas myarray can never be assigned anything and will always represent the same block of 20 elements of type  int .

# Pointer Initialization
    # At the time of Declaring Pointers you can also Initialize them.
    int * myptr = &myvar;
    int myvar;
    int * myptr;
    myptr = &myvar;

# Pointer Arithmetic in C++ ( increment, decrement, etc.. )?
    # Arithmetic Operations with Normal C++ variables
    int i = 0;
    cout << i << endl;    // prints   1
    # Pointer Arithmetic Operations with special Pointer Variable
    int myvar = 10;
    int * i = &myvar;      // This is a pointer variable of type Integer
    // let i = 0x454545454     this is a memory address of variable  myvar
    i++;    // Increase pointer to one level.
    cout << hex << i << endl;  // prints  0x454545458
    // Because pointer variable i is of type int, so when we increase pointer variable one unit then it actually incremented by sizeof(myvar) to make sure that pointer will point to next address not in middle of any memory address.  
    char * mychart;   //     sizeof(char)
    short * myshort;  //     sizeof(short)
    long * mylong;    //     sizeof(long)
    *p++     // same as  *(p++)  increment pointer, and De-reference un-incremented address
    *++p     // same as  *(++p)  increment pointer, and De-reference incremented address
    ++*p     // same as  ++(*p)  De-reference pointer, and increment the value it points to
    (*p)++   // De-reference pointer, and post-increment the value it points to.

# Pointer with const ?
    # If you can access the content of a variable using pointers then you can also modify the content.
    # I want a read-only pointer so that i can read the content but i can not modify the content.
    int x;
    int y = 10;
    const int * p = &y;
    x = *p;    // OK, you can read the content where pointer points to.
    *p = x;    // ERROR, pointer points to content in const-qualified manner.

    # Pointers are variables, too, and hence the  const  keyword that is relevant to variables is relevant to pointers as well. However, pointers are a special kind of variable that contains a memory address and are also used to modify a block of data in memory.

      # there are three cases:-
      # when, the DATA, a pointer is pointing to is constant,
         and can not be changed, yet the address contained in the pointer can be changed,

         means, the pointer can also point elsewhere.

        g++> int HoursInDay = 24;
        g++> const int* pInteger = &HoursInDay;
        g++> cout << pInteger << endl;
        g++> cout << &HoursInDay << endl;
        g++> cout << *pInteger << endl;
        g++> int MonthsInYear = 12;
        g++> pInteger = &MonthsInYear;
        g++> cout << *pInteger << endl;
        g++> cout << pInteger << endl;   // pointer contained address will be changed..
        g++> *pInteger = 13;
        [Compile error - type .e to see it.]
        g++> .e
        <stdin>: In function ‘int main()’:
        <stdin>:19:11: error: assignment of read-only location ‘* pInteger’
        g++> .u
        [Undone '*pInteger = 13;'.]
        g++> int* PAnotherPointerToInt = pInteger;
        [Compile error - type .e to see it.]
        g++> .e
        <stdin>: In function ‘int main()’:
        <stdin>:19:29: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]

      # when, the ADDRESS contained in the pointer is constant and can not be changed, yet  the data pointed to can be chaged.
        g++> int DaysInMonth = 30;
        // defining a constant varaible pointer of type int
        // you can change the data conatined in the memory address, but you can not change the memory address
        // the pointer is pointed to..
        g++> int* const pDaysInMonth = &DaysInMonth;
        g++> *pDaysInMonth = 31;
        g++> int DaysInLunarMonth = 28;
        g++> pDaysInMonth = &DaysInLunarMonth;
        [Compile error - type .e to see it.]
        g++> .e
        <stdin>: In function ‘int main()’:
        <stdin>:15:14: error: assignment of read-only variable ‘pDaysInMonth’

      # when, Both the address contained in pointer and the value being pointed to are constant and cannot be changed (most restrictive variant):
        g++> int HoursInDay = 24;
        // So, pointer can only point to HoursInDay
        // You are not allowed to change the pointer address and pointer point to that DATA.
        g++> const int* const pHoursInDay = &HoursInDay;
        // If you try to change the DATA, pointer point to, you get an ERROR message.
        g++> *pHoursInDay = 25;
        [Compile error - type .e to see it.]
        g++> .e
        <stdin>: In function ‘int main()’:
        <stdin>:12:14: error: assignment of read-only location ‘*(const int*)pHoursInDay’
        g++> .u
        [Undone '*pHoursInDay = 25;'.]
        g++> int DaysInMonth = 30;
        // If you try to change the address the pointer contains..
        g++> pHoursInDay = &DaysInMonth;
        [Compile error - type .e to see it.]
        g++> .e
        <stdin>: In function ‘int main()’:
        <stdin>:13:13: error: assignment of read-only variable ‘pHoursInDay’

    int x;
        int *       p1 = &x;  // non-const pointer to non-const int
    const int *       p2 = &x;  // non-const pointer to const int
        int * const p3 = &x;  // const pointer to non-const int
    const int * const p4 = &x;  // const pointer to const int    

# Pointers to String literals?
    # String literals are arrays containing null-terminated character sequences.
    # String literals are arrays of proper array type to contain all its character plus the terminating null-character, with each of the elements being of type const char, as literals, they can never be modified.
    const char * foo  = "hello";
    # Because pointer  foo  points to a sequence of characters, And because pointers and arrays behave essentially the same way in expressions, foo can be used to access the characters in same way arrays of null-terminated character sequences are.
    g++> #include <iostream>
    g++> const char * foo = "hello";
    g++> std::cout << "Hello world!"<< std::endl;
    Hello world!
    g++> std::cout << foo << std::endl;
    g++> std::cout << *foo << std::endl;
    g++> std::cout << *(foo+1) << std::endl;
    g++> std::cout << *(foo+4) << std::endl;
    g++> std::cout << foo[4] << std::endl;

# Pointers to Pointers?
    # Pointers to Pointers, means you want to nest them, you are looking for a pointer that can pointer to a pointer instead of content.
    # Example :-
    int a = 492010;
    int * b = &a;
    int ** c = &b;
    cout << a <<  << b <<  <<  c  << endl;  => 492010  0x7fff11cb53fc  0x7fff11cb5400
    cout << a <<  << *b <<  <<  *c  << endl;  => 492010  492010  0x7fff11cb53fc
    cout << a <<  << *b <<  <<  **c  << endl;  => 492010  492010  492010
    cout << &a <<  << &b <<  <<  &c  << endl;  => 0x7fff11cb53fc  0x7fff11cb5400  0x7fff11cb5408
    cout << &a <<  << &b <<  <<  *&c  << endl;  => 0x7fff11cb53fc  0x7fff11cb5400  0x7fff11cb5400

# Void Pointer?
    # void type of pointer is a special type of pointer in C++.
    # void pointers are pointers that points to a value that has no type, if no type for a variable, means undetermined length and undetermined De-reference properties.
    # This gives void pointers a great flexibility, by being able to point to any data type.
    # But they define a great limitation for it, the data pointed by them can not be directly De-referenced.
    # So any address in a void pointer needs to be transformed into some other pointer type that points to a concrete data type before being De-referenced.

# Invalid Pointer or NULL Pointer?
    # because Pointers are just like normal C++ variables that can hold memory addresses, If memory address hold by a pointer does not exists or points to invalid element, means out pointer is Invalid.
    # for example, uninitialized pointers and pointers to non-existent elements of an array.
    int * p;    // uninitialized local variable ( isPointer: True )
    int myarray[10];
    int * q = myarray+20;  // Invalid pointer, element out of bounds
    # You can explicity point a pointer to nowhere. ( use of null pointer value )
    int * q = 0;
    int * p = nullptr;
    int * r = NULL;
    # all are same, means null pointer, points to nowhere.

# Pointers to Functions?
    # C++ allows operations with pointers to functions. The typical use of this is for passing a function as an argument to another function.
    # when you want a pointer points to a function just enclose function name in  parentheses () and and asterisk ( * ) is inserted before the name.
    int (*minus)(int, int);
    # function aliasing with the help of function pointers
    int (*minus)(int, int) = subtraction;
    # we want to create a pointer to a function named 'minus' that will points to pre-defined function named 'subtraction'.

    # References :-

No comments :