Saturday, February 29, 2020

POINTERS

Pointers are special variables that are responsible to store the l-value of a variable.
Let us clear of conception about l-value and r-value.
Well, r-value stands for real-value.
On the other hand, l-value stands for location-value.


Suppose we consider the following declarations as given below
i) int a=2;
in the above initialization, a is a variable that refers to a value of 2.
In other words, a memory address is created at a random memory location with name as 'a' and the value stored in that memory location is 20.
Now as shown here a is the name, 20 is the r-value and 400 is its address or l-value.
As now we are through with these let's dive into the depths of next syntax

ii) int a=2
int *p=&a









Now see in the first statement a variable with name a points to a value 20 with l-value as 400. In the second case, we have a pointer with name p that points to the address of variable 'a' or 400 and stores it into a separate memory address i.e. 600.


Now we shift to our second important topic under pointer.

POINTER AND ARRAY

An array is a contiguous memory allocation where numbers are stored in a continuous form. 
For example suppose, we are given an array
int a[]={5,10,7,9,8};//line 1
int *p=a;//line 2
int *p=&a;//line 3
What is the difference between the 3 lines?
line 1 initializes an array with certain values
line 2 is not an error. In the case of an array, the name of the array itself becomes the pointer base address. 
line 3 is also fine. It states that a container is created which stores the total array a.
Let us take an example.

This is an example of the container of an array but it is referenced by the first index of the array.

Now let’s look at certain notations in a pointer.
int a[2]
int *(a+2)
int 2[a]

Which of the above is correct?
Though it may not look but all three are accepted and are correct.
The first statement is obviously correct.
a[2]=*(a+2)
For any pointer operation
*(a+i)=a[i] where i is a constant.
Now *(a+i)=*(i+a)
a[2]=2[a]

Thus, all are the same.
Q) if A={2,5,6,7,8,0}
Find i) A[2] ii)3[A] 

Pointer addition
Now pointer addition is somewhat different from normal addition.
Suppose we are give a pointer with name A and asked to find the value of
*(A+2)
The * operator is address of operator. Well in this case our address value is calculated as
Resultant address= Base Address(A)+ data_type(A)*i…..here * means normal multiplication.
Now that we are through this lets take the previous question and add a subpart to it.

iii) Find *(A+1)

Storage of pointers
Since we are on the context of datatypes let’s make this very clear that every pointer irrespective of its type occupies 2B. Although certain books say that since pointer always store addresses and addresses are necessarily numbers. Numbers are of 2B, hence, each pointer occupies 2B.
So, just solve the below sum
i)                sizeof(void *d)-sizeof(int *f)*sizeof(char *h)
ii)              sizeof(void *d)-sizeof(int *f)*sizeof(char *’c’)
Well both looks similar but they are not. The first one gives -2 as sizeof() returns size of a variable or datatype in Bytes(B).
The second one is an error.
In pointers we can only pass variables or memory addresses but not a constant like ‘c’.

Memory allocation of Pointers
To understand the memory allocation, we need to understand how the memory looks like.


Any pointer when not allocated memory resides in the heap memory.
There are generally 2 types of methods to allocate memory.
Static allocation: This is the type of allocation that take place during compilation.
Dynamic allocation: This is the type of allocation in which the amount of memory to be allocated is known during the runtime. These values are stored in the Heap section.
The space in between heap and stack memory is the freely expandable space. Heap expands in the downward direction and Stack expands in the upward direction. At the time when both collides and there are no space for any memory allocation then it becomes crashing.
Dangling pointers
Dangling pointers arise during object destruction when an object that has an incoming reference is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory.
Suppose we have a pointer that was pointing to a certain value. Now if that value gets deleted somehow but this pointer does not change its r-value leading to a dangling pointer situation.
Let’s see this with an example
int a=30;
int *p=a;
int *s=Null;
s=p;
delete(p);
print(s)// we are referring to s and this is not an error but the value is irrelevant. Hence this leads to dangling error.
Why the notion of the pointer may become dangerous?
Pointers may appear to be harmless but it can do some great damages. Some of these are mentioned below:
           Suppose if the pointer takes any system address as its value then it can cause those system values to change and we may face problems.
Let’s take an example to understand. The world’s most simple virus can be made by just checking the address of Caps-Lock and assigning it to a pointer. Now definitely Caps-lock may be either ON/OFF denoted by 1/0 respectively. Now suppose if we take the value and perform bitwise OR operation of the above mentioned Caps-Lock value with 1, the answer will always remain 1. Hence, we cannot write any C, C++, Java or Python codes. Because they are all case sensitive.
Remedy: Always initialize your pointers to NULL and do not allow the pointer to randomly take up a value.

int*p=NULL;
Here we are not allowing the pointer p to take up any garbage value as data.

2)     Another prominent case is when suppose, we dynamically allocate some memory, but forget to free the memory then our memory remains allocated leading to increase in Heap memory and may sometime go on to crash completely.
Remedy: The only remedy in such situation is that dynamic allocation and deallocation must take place anywhere when allocation is needed.
Because of these problems certain programming languages like Java, Kotlin has removed pointers totally.
Self-Referential structure
Suppose the definition of a structure of a structure is given as below
struct demo1                                                                           struct demo2
{                                                                                               {
            int a;                                                                                        int b;
            struct demo2 p;                                                                       struct demo1 r;
}k;                                                                                            }m;

Now suppose when object of struct demo1 is to be created, it calls creation of demo2 struct which in turn calls calling of object of demo1 and this process continues till the total memory is exhausted.

How to solve this problem?
Well, again pointers coming to our rescue. Let us see how
struct demo1                                                                           struct demo2
{                                                                                               {
            int a;                                                                                        int b;
            struct demo2 *p;                                                                      struct demo1 *r;
}k;                                                                                            }m;
Now when we create an object of demo1, the object need not call object formation of demo2. As the size of any pointer is 2B, size of demo1 can be easily calculated as 4B. Similarly for demo2 it is 4B.

This is how pointer to an object of another structure solves the crashing problem. Although the above structure is stable but definitely this is not a self-referntial structure.
A self-referential structure is one which calls another object of same type in the same structure. Let us see an example.
struct Tree
{
            int key;
struct Tree *left,*right;
}root;

Here we find that inside the structure, same structure is called. These are self referential structure.
SOME COMPLEX FUNCTION PROTOTYPES
1)     int f(float)   >>>A function with name f taking a float value and returns an integer value
2)     int *f(int)      >>>A function taking an integer value and returning an int type pointer
3)     int (*f)(int)    >>>A pointer to function referred to by ‘f’ which takes an integer argument and returns an integer value
4)     void (*f[10])(int)>>An array of pointer to function which takes an int value as argument and returns no value.
5)     Int *(*a[5])(int)  >>>An array of 5 pointer to function which takes an integer value as argument and returns a pointer to integer in each case.
6)     float ***f(double ***)>> A function that takes pointer to pointer to pointer of double argument and returns pointer to pointer to pointer to float as return value.
7)     char (*f)(int (*)[3])>>>>A pointer to function referred by F that takes a pointer to an array of size 3 as argument and returns a char type data.
8)     Char(*(*f[3])(int))[5];>>>An array of 3 function pointers which takes an integer value and returns a pointer to array of size 5 of char type
9)     Float(*(F(int *)))[3]>>>>A function that takes an integer pointer as argument and returns a pointer of an array of size 3 of float type.
10)   Float *F(int *)[3]>>>>>>A function which takes an integer pointer and returns a pointer array of float type
11)  Char (*(*F())[3])(int)>>>A function which takes no argument and returns a pointer of which in turn is a function of array of size 3 pointer which takes an integer argument and return a char value.
12)  Void (*F)(int,void*(*)())>>>A pointer to function ‘F’ that takes an integer and a pointer of function that returns a void pointer which in turn returns no value
13)  Int **(*F)(int **,int **(A)(int **,int **))>>>A pointer to a function referred by ‘F’ which takes a pointer to pointer of integer and a function A which takes 2 pointer to pointer of integer as arguments and returns pointer to pointer of integer which in turn returns a pointer to pointer of integer.




                       

No comments:

Post a Comment