Pointers in c


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Pointers in c

  1. 1. What will be coveredPointers  Pointer definition  Initialization  Dereferencing Pointers  Constant Pointer  Pointer Arithmetics  Adding or subtracting integer from pointers.  Pointers and Arrays  Pointers as arguments  Memory Management using Pointers  new operator  delete operator Lecture 7: Pointers 1
  2. 2. Pointers Pointers are variables like any other type. However they are also derived type like arrays. Just like other variables, you need to declare pointers before using them and there must exist one and only one definition for each variable of type pointer. Pointers can be used to hold “memory address ” of other variables of a given type. However just like, each variable has a type, pointers also have type, like  Pointer to an int. It can be used to hold addresses of only and only int variables (not even unsigned int)  Pointer to a char, hold addresses of only and only char  Pointer to an object of any user defined type such as say “shape”. Lecture 7: Pointers 2
  3. 3. Why Pointers should have type? Why type?  Unless you would tell what type of address pointer is pointing to, compiler would not know how to use (interpret) that pointer. Example:  If pointer to double, that means next eight bytes are holding the double in a particular way.  If unsigned, that means two bytes, with no sign bit.  If char, means ASCII value in single byte.  To perform what is known as pointer arithmetic’s you need to know size of element to which pointer is “ pointing”.  To be able to have compile time error checking, making your program more robust, you need to specify type.  However language gives you freedom to cast it to pointer of most of the other types, thus giving you all the freedom. So, type of variable to which it is pointing is firmly attached with all pointers. Lecture 7: Pointers 3
  4. 4. Defining Pointers Pointers are a powerful tool and should be used carefully. Whenever you need to use it, you have to define them first. Pointer have a name, just like other variables. Same naming convention, as for variable, is used for pointers. Name of pointer is different than the name of variable to which they may be pointing (don’t get confused here). Example  int *pi, *pj, *pk; // three pointers to int // with names pi, pj and pk  char *str; // pointer to char Here ‘*’ is used to indicate it is pointer variable and not int. Note that * needs to be used for every variable declaration separately. So, int *pi, pj; /* defines two variables, pi is pointer to int and pj is normal int variable and not a pointer */ Lecture 7: Pointers 4
  5. 5. Correct Pointer Definitions Correct examples of Definitions are:  double* abc; // * can be close to double or abc double *bcd; // Ok, however you need * with every pointer. double *cde,* def, * efg; // 3 pointers each of type pointer to double  You can defined pointer to derived or user defined types as well, However, definition depends upon operator precedence int *fgh[5]; // Since precedence of [] is higher than *, this is array of // 5 pointers to int and not pointer to array of 5 ints int (*ghi)[5]; // This is single pointer to array of 5 ints.  Similarly if say Shape is user defined type than Shape * hij; // hij is pointer to Shape (UDT, definition of which should // come before this definition of pointer).  We can also have pointer to pointer int * * ijk; // ijk is pointer to (pointer to int). I.e we can store address // of any pointer to int in ijk.  Similarly there could be pointer to pointer to pointer of a type & so on… Lecture 7: Pointers 5
  6. 6. Wrong Pointer Definitions Wrong Definitions of pointers are:  double abc *; // * can not be after the name  * double bcd; // * can not be before the type name.  double *cde, def; // if we want def to be pointer there // must be a * before it  pointer * efg; // Type has to be specified (pointer is not a keyword) * fgh; // Error, if type is completely missing  Shape *ghi; // if Shape has not been defined so far.  int & ijk; // we cannot use & or other operators in place of * // & means reference and not pointer Lecture 7: Pointers 6
  7. 7. Pointer Initialization You need to set proper values (address) to pointers just like you set values for variables, before you can use them. This is how you can set proper values for local and global pointer variables  Initialize them at the time of declaration with address of a known variable, example int *pi=&i; /* initialized to address of i. i should only be of type int and should already be defined or declared in the current file. i could be local or global variable */  Here ‘&’ is acting as “address of” operator  If not initialized, it can later be assigned an address of any variable of the same type, before using it int *pi; pi=&i; /* assign address. This can be done multiple time. You may assign it the address of any other variable at any time */ Lecture 7: Pointers 7
  8. 8. Dereferencing pointers Ok, so you have also initialized or assigned the address to our pointer. Now what? You can perform following actions  You can dereference the pointer to get the object to which your pointer is pointing. Example int *pi=&i; (*pi)=76; // same as i=76; here * is deference and not pointer  In other words, you can use (*pi), anywhere you can use int variables, even on left side. You don’t need (), but can be used for clarity. I.e. you could say *pi=3*4+7;  You can perform pointer arithmetics. Discussed later  Pointers can be used to pass arguments to function which the functions can modify (Equivalent to Pass by reference).  Pointers are used to allocate memory at run time as per your needs (Memory Allocation). Discussed at the end Lecture 7: Pointers 8
  9. 9. Pointer to constant You can define  Pointer to a const variable, as follows  const int *pi=&i; //also int const* pi  i itself need not be a const variable. It could be any normal variable, however when referenced through pi, we cannot modify i.  Now you cannot use (*pi) to modify the contents of i. However you can use it to access the contents of i. (*pi)=10; // error (*pi)++; // error int j= (*pi)+56; // OK as we are not modifying i  You can still make pi point to another variable of type int, example pi=&j; // ok for pointer to const variable // Note: when assigning address you should not // use *pi instead use pi itself. Lecture 7: Pointers 9
  10. 10. Constant Pointer You can also define const pointer to a variable, as follows  int *const pi=&i; // use const after ‘*’  It must be initialized (not assigned afterwards) because we are defining a constant pointer, which can not be assigned later on.  You can modify i using (*pi), as follows (*pi)=10; // OK, variable is not constant (*pi)++; // OK  However now pi cannot point to any other variable pi=&j; // ERROR, constant pointer Similarly we have const pointer to a const variable  const int * const pi=&i; // or int const * const pi=&i;  Now we cannot modify i through pi or assign address of any other variable in pi. We can use it only to access value of i at any time. (*pi)=10; // Error (*pi)++; // Error pi=&j; // Error j = (*pi)+56; // OK Lecture 7: Pointers 10
  11. 11. Pointer Arithmetic You can add or subtract a integer from all those pointers which are not declared const pointer, example int *pi=&i; pi+=10; // No compiler error, now pi is pointing to // 10 th int’s address from the address of i pi++; // pi is further incremented by one --pi; // decrement pi by one. pi=pj-j; // where pj is another pointer and j is int Note: When performing arithmetic it is on pi and not (*pi) You can subtract two pointers of same type to get an int, example int *pi=&i; *pj=&j, k; k=pi-pj; // value of k would be int /* it would return number of elements of pointer type and not number of bytes */ Lecture 7: Pointers 11
  12. 12. Pointer Arithmetic When we perform pointer Arithmetic, Compiler assumes that the address that our pointer is pointing to belongs to array of the type of variables to which our pointer belongs. That is Given int i, *pi=&i; /* compiler assumes pi contains address of an array of int’s */ Therefore when we say pi++; Compiler changes the address in pi so that it is now pointing to next integer, I.e. address which is 2 bytes from the original address. (compiler does not bother whether it is actually int or not, it simply assumes it is int and will try to interpret that memory as int). So, if we increase the address in double pointer by one, it now points to next double (I.e. 8 th byte’s address from original address) Remember, when we are performing pointer arithmetic it is on pointer pi and not on (*pi). Lecture 7: Pointers 12
  13. 13. Pointer and Arrays Pointers and Arrays go side by side. In fact array is implemented as const pointer  When you define array variable, two things happen  A const pointer is created with the name of the array variable  Enough continuous memory is reserved (allocated) in data segment (not on heap) and address of its first element is stored in the array variable (in other words const array pointer is properly initialized)  Now pointer arithmetic is used to access elements of array  Example  int arr[10]; // array of ten int’s  variable arr is actually implemented as int * const arr and initialized to the Address of memory allocated (10 int’s)  Now if you use, for example arr[5]; compiler would replace this with *((arr)+(5)); This is why index start from 0 and not 1.  i.e., it would dereference the 5th address from the address of first element, which would be address of 6th element. Lecture 7: Pointers 13
  14. 14. Pointer and Arrays Example continues…  Note that we cannot change the value of arr itself, but we can use it’s value to access rest of the elements  Even in case of pointer, you can add or subtract integer value (or variable) from a pointer and then dereference it  Compiler would simply try to access whatever is there at the computed address as a type of that pointer  So, if you say int *pi=&i; // initialize with address of a variable *(pi+3)=10; // compiler would try to access 6 th and 7 th bytes from the address of i, as variables of type int. It would not generate any error message, if those bytes are actually not int, or if they have not been allocated by your program  So, it’s the responsibility of programmers to ensure that you are accessing proper memory locations using pointers Lecture 7: Pointers 14
  15. 15. Pointer as Arrays So, if they have so many similarities can pointers be used with similar notation as of array Why not! Example int *pi=&i; pi[2]=10; // same as *(pi+2)=10; Hey but you are using address of single variable as address of array That’s why I said in beginning, its powerful tool, use carefully. YES you can and no compiler errors, but surely run time errors (even collapse of OS) Compiler cannot differentiate between pointer to single variable or pointer to array. So, can array variables be used as pointer notation. Yes, as long as you are using them as const pointer int arr[10]; *(arr+i)=67; // same as arr[i]=67; Lecture 7: Pointers 15
  16. 16. Pointer as function argument Pointers can be used as a function argument as follows: say we want to define a function which takes pointer to int as argument void myFunc(int * pi); // function prototype In the function body, use pi, as if it has been properly defined & initialized void myFunc(int *pi) { *pi=10; // use pi as defined and initialized pointer } At other places, where you need to call that function, you would need to supply ADDRESS of VARIABLE (or address of constants if the argument is defined as const pointer) myFunc(&i); // Ok, whether argument is normal or const pointer myFunc(&45); // only if argument is defined as const pointer myFunc(i); // ERROR, supply address of int and not int itself You may also pass pointer to int (not address of pointer to int) int i=20,*pi; pi= &i; myFunc(pi); // OK, However after this call value of i would change. myFunc(&pi); // ERROR, don’t supply address of pointer to int Lecture 7: Pointers 16
  17. 17. Memory Management Using pointers we can take memory management in our hand and we can directly control lifetime of variables. I.e. we can create variables whenever we want and destroy them after we have used them. Suppose, we want to create a variable in one function say f1(); and then use them even after that function is finished. This is how we can create a variable in function f1(); int *pi; // pi is some global pointer to int void f1() { pi = new int; // using operator new // now use pi as we want, it is pointing to an unnamed int } Here new operator is used which work as follows  When we use expression new anytype; // anytype could be fundamental, derived or user defined type  Than new operator allocates enough memory for one variable of type anytype  It than returns the address of the memory which is allocated. We can store this address in pointer to anytype . Lecture 7: Pointers 17
  18. 18. Releasing Memory Now using that pointer (I.e. by dereferencing that pointer), we can use the recently allocated variable as we want. When we don’t want to use that variable any more, we can release the allocated memory as follows delete pi; // delete is an operator, which release memory Deleting an earlier allocated pointer, more than once is programming error. Not deleting it even once, though not an error, but leads to memory leaks which could be bad if your program performs lot of memory allocation. Deleting a pointer which is properly initialized with address of a variable which is not allocated by you, may not lead to run time error, but is programming error. int i=10, *pi=&i; delete pi; // no runtime error but programming error Pointers can be assigned null value myClass *ptr; // myClass is some user defined class ptr=0; // null pointer delete ptr; // deleting null pointer, even multiple times, has no side effects Lecture 7: Pointers 18
  19. 19. Allocating Arrays Using new operator we can even allocate more than one variable example int *pi = new int[40]; // allocate 40 int’s and store address of first pi[3]=10; // int in pi so that using pi, we can use all 40 int’s pi[39]=20; // now pi just as array of 40 int’s Since new operator can take expression using variable, we can dynamically allocate memory as per our requirement. Example int size; cout << “Enter size of char array: “; cin >> size; char *pd = new char[size]; // array size will be decided at run time We can even allocated user defined type using new operator. Remember, that address returned by new operator is useful till we want to use the allocated memory and so it should usually not be stored in local pointer objects, which would be lost at the end of that function. If so, than we would not be able to deallocate that memory.Lecture 7: Pointers 19
  20. 20. Exercise There would be a quiz before the next class. Write a program which will take input of any number of integers till –1 is entered. It will than display each separate number that was input along with number of times it was input. Interaction with program should be as follows: Number: 34 Number: 34 Number: 45 Number: -1 Number 34 was specified 2 times Number 45 was specified 1 times Lecture 7: Pointers 20
  21. 21. Exercise contd… Write a program which would make spiral matrix. Interaction with program should be as follows. Enter size of matrix (odd): 5 Writing matrix… 17 16 15 14 13 18 5 4 3 12 19 6 1 2 11 20 7 8 9 10 21 22 23 24 25 Can you modify the program so that it also ask for starting direction and rotation (clockwise or anticlockwise) and makes matrix as per that direction and rotation. Lecture 7: Pointers 21