Skip to content

Latest commit

 

History

History
575 lines (505 loc) · 33.4 KB

File metadata and controls

575 lines (505 loc) · 33.4 KB

C_Plus_Plus_Intermediate_Pointers(I)

Its an intermediate guide series on C++

1. Pointers

A pointer is a entity which cointains a memory address and specified location of computer memory.

Suppose integer i = 10 which has address in the memory location FFFF4 and *p is a pointer which assigned to address of integer i through & → address operator. Now if we makes output of *p we get 10 i.e *p which contains address of i i.e. FFFF4 points to that address and fetch the value from that address.

Dereferencing operator(*)/Indirection Operator(*) :→ Dereferencing is an operation performed to access and manipulate data contained in the memory location 'pointed to' by a pointer. The operator '*' is used to deference pointers.

Note : int *p = &i; similar to operation : *&i

Similarly, *ptr is a pointer variable and ptr=&i and *ptr = 20 , then 20 is saved to address of variable i which is possible only because of dereferencing operator.

int *ptr → ptr is a pointer to an integer , char *ptr → ptr is a pointer to a character , double *ptr→ ptr is a pointer to a double ..... etc.

Pointer Variable

int *ptr ; Here int is a data type , * → is dereferencing operator (pointer) and ptr→ is pointer variable.

<data_type> *<ptrvar_name>

Pointer in function(Call By Reference)

1. Call By Reference :- When address of actual parameter is copied to formal parameter(Address used as reference) for execution of the function.

2. Passing Argument By Reference :- When pass by reference technique is used , the address of the data item is passed to the called function(Call By Reference) i.e. reference address of the actual argument is passed to the formal argument.

 Function Declaration:
<return_data_type> function_name (data_type_1 * , data_type_2 * ,......, data_type_n *);
 Function Definition:
<return_data_type> function_name (data_type * formal_argument_1,data_type * formal_argument_2,...., data_type * formal_argument_n)
{
///Function Body
}

Note: Each formal argument is a pointer variable.

 Function Call:
 function_name (&actual_argument_1, &actual_argument_2,...., &actual_argument_n)

More Examples on Pointers

Note : We have
 Function Definition:
 return_type function_name(datatype pointer_variable){
 //function body
 }

such as :

 int lengthOfDigits(int *number){
 //function body
 }

Then , in main() function either we call :

function_name(address_operator variable_name);

Such as:

lengthOfDigits(&i);

Or We assign :

data_type pointer_variable = address_operator variable_name; 
function_name(pointer_variable);

Such as:

int *ptr = &i;
lengthOfDigits(ptr);

i.e. *ptr holds address of variable i and it fetch the value when it is called. Note →Both the way, it satisfies function declararion :

 Function Declaration:
<return_data_type> function_name (data_type_1 * , data_type_2 * ,......, data_type_n *);

Pointers in Recursive Function

1. Print Number from 1 to range

2. Sum of numbers

3. Count Of Digits

4. Fibonacci Series

5. Factorial

Note 1 : (*ptr_var) → Bracket priortize the pointer variable for the operation. Similarly, *ptr_var = &i and *ptr_var = *ptr_var +1 ; is a valid pointer operation which will fetch the value of the i referencing through the address and will update it adding 1 to the value of variable i i.e. if i =10 then , output will be 11.

Example

Note 2 :Also in recursion when :

 Recursion:
<return_data_type> function_name (data_type *ptr_var){
data_type var = *ptr_var;
return function_name (&var);
};

Such as:
int display(int *i){
int j = *i;
display(&j);
}

Here the &j or &var [address of var/j] everytime gets assigned to *i or *ptr_var to complete the process i.e *ptr_var → &var / *i → &j

Example

Pointers Action in For Loop (Same logic for other Loops)

Void Pointers

1. Operation of Void Pointers at different Data Types

2.Operation of Void Pointers in Function

3.Operation of Void Pointers in For Loop

4.Operation of Void Pointers in Recursion

Note: Void Pointers uses the reserved word "void" for specifying the type of the pointer.Pointers defined in this manner donot have any type associated with them and can hold any address of any type of variable i.e.

 int *ptr_var;
 int var;
 char var_1;
 ptr_var  = &var;

But It cannot be:(Invalid)

ptr_var = &var_1; //Invalid

(As ptr_var is int type pointer variable cannot store address address of character variable's address(Conversion Error:
Cannot convert char* to int *)

But it cannot be with void pointers . We can assign several data_type variable addresses with single void pointer.

void *vd_ptr;
int var;
char var_1;
vd_var  = &var; //valid
vd_var = &var_1; //valid

Also while output we write : *((data_type *) vptr) , here (data_type *) is typecasted [pointer typecasting ]over void pointer variable to identify which type of datatype output we want , the reason is same : That is Void Pointers uses the reserved word "void" for specifying the type of the pointer.

Pointer Arithmetic

Pointer Arithmetic is the Arithmetic based on Address hold by Pointer Variable.

Based on Valid Pointer Arithmetic Operation , program given below :

Valid Pointer Arithmetic Operation

A Multiplication Technique With Pointer (*ptr_var1 ** ptr_var2 => (*ptr_var1) * (*ptr_var2))

Increment and Decrement of Pointer Address

Note: The adress of a pointer divided into two parts : 1) Segment and 2)Offset. The segment address, located within one of the segment registers, defines the beginning address of any 64K-byte memory segment. The offset address selects any location within the 64K byte memory segment. Segments in the real mode always have a length of 64K bytes.

 

Hence offset is a small part of the segment . Normally all pointers defines in a program in the small model contain only the offset part of the address. Such pointers are called Near Pointers, which lie within a single segment only. The limitation can be overcomed by use of pointers, which are capable of holding both the segment as well as the offset part of an address. Such pointers are known as Far Pointers.

Memory model Segment Pointer Type
Code Data Stack Code Data
Tiny 64k near near
Small 64k 64k near near
Medium 1MB 64k far near
Compact 64k 1MB near far
Large 1MB 1MB far far
Huge 1MB 64k 64k far far
Data Type Data Size Pointer Type
near far
char 1 2 4
short 2 2 4
int 2(16 bit compiler) 2 4
4(32 bit compiler)
long 4 2 4
float 4 2 4
double 8 2 4
Invalid and Illegal Use of Pointers Examples:
-----------------------------------------------
int a , b , *p, *q;
p = -q; //Illegal use of pointers [uniary minus]
p = p << 1; //Illegal use of pointers [int* to int conversion]
p = p - q ; // Invalid :Nonportable pointer conversion 
p = p - q - a; // Invalid :Nonportable pointer conversion 
p = p + a; //Invalid Pointer Addition
p = p + q;//Invalid Pointer Addition
p = p * q; // Illegal use of Pointer
p = p * a; //Illegal use of Pointer
p = p / q ; //Illegal use of Pointer
p = p / b ; //Illegal use of Pointer
p = a / p ; //Illegal use of Pointer

  --------

Pointers to Pointers

Where pointer (*ptr) store the address of a variable say var where data is stored say 10 . Then **ptrptr(Pointers to pointers) store address of that pointer (*ptr)and use it as a reference to fetch data from variable var through (*ptr).

Applying Pointers to Pointers in Functions

Pointers To Pointers in Recursive Function

1. Print Number from 1 to range

2. Sum of numbers

3. Count Of Digits

4. Fibonacci Series

5. Factorial

Pointers To Pointers Action in For Loop (Same logic for other Loops)

Pointers to Functions

A pointer to a function can be defined to hold the starting address of a function, and the same can be used to invoke a function. It is possible to pass addresses of different functions at different times thus making the function more flexible and abstract.

ReturnType(*PtrToFn)(arguments_if_any)

Invoking a Function using Pointers:
----------------------------------
(*PtrToFn)(arguments_if_any)
or
PtrToFn(arguments_if_any)

Passing Function Address To Function Argument

The address of a function can be passed as an argument to a functions, either by a function name or a pointer holding the address of a function.

Recursive Call To Main() Function

main()→cannot be invoked recursively, cannot be overloaded, cannot be declared inline, cannot be declared static in C++. But if we assign the address of main() to any Pointer To Function having same return type of main() then invoking the Pointer To Function , main() function can be called Recursively, violating the first rule.

Pointer to Constant Object

It indicates Pointer to constant object which store address of integer variable , Pointer to constant object which store address of character variable etc. That is we cannot manipulate the assigned variable's value by referencing the variable's address through the pointer variable as referencing Object is constant.

Syntax: const <dataType>* <var>; 

  is same as : 

<dataType> const * <var>
  
Such as:
const float *ptrpi;
float pi = 3.14f;
float area = 0.14f; 
ptrpi = &pi; //Allowed
ptrpi = &area; //Allowed
ptrpi = ptrpi+1;// i.e. Pointer Arithmetic is Allowed
*ptrpi = 10.15 ; // Trying to change value using address as a reference is not allowed as Object (ptrpi) is constant.

Similarly,
const float *ptrpi; is same as float const *ptrpi;

Constant Pointers

Constant Pointers tells its assigned address is fixed and constant .

Syntax:  <dataType>* const <var>; → Constant Pointer To An Object which store address of a <dataType> Variable.

Such as : - int * const pi ; → Constant Pointer To An Object which store address of Integer Variable(Stored Address is Constant) 
but Object(pi) is not Constant.

Hence we can change values like :
  
int * const pi;
int i = 10;
int j = 20;
pi = &i;
*pi = 30;
*pi = 40;
Output will be 40.
But if we assign another address to the pointer i.e. 
  
pi = &j;

, it will refuse and generate error as it(pointer) is constant 
i.e. it's assigned address is fixed and constant.

Also, 
pi= pi+1 ; // Arithmetic Operation on Pointer Address is not Allowed and Possible here as Address is Fixed and Constant
,hence it will again refuse and generate error. 
 
  


Syntax: const <dataType> const * <var>;  → Constant Pointer To A Constant Object.



Here we cannot change values as Object is constant .

Such as :

const int* const pi;→ Constant Pointer To An Object(pi) which store address of Integer Variable(Stored Address is Constant) and the Object(pi) is also Constant.

int i = 10;
*pi = &i;
Then *pi = 20 is not possible. It Output 10 only, as pointers to const cannot be used to change the value of variable as Object (pi) is constant.
pi = &j; → It refuses again(not possible) and generate error, as Address assigned at first to Pointer Variable is fixed and Constant.
pi = pi + 1; →It refuses again and generate error, as  Arithmetic Operation on Pointer Address is not Allowed and Possible here as 
  Stored Address under Pointer Variable(Which is a constant object) is Fixed and Constant.

Note: During Recursion , we have seen similar type of operations as depicted to the pictures below:

And Similar type of operations is possible in Pointers to Pointers.

Understanding it with 2 examples as given below :

Note:

*ptr and cout<<(int)ptr → would produce permission error if run on TDM-GCC and compiler could restrict the type cast convertion . In such case use MinGW to avoid such error.