340 likes | 352 Views
Pointers. Pointers. What is pointer? A variable (2 or 4 bytes long) that can hold an Address Why pointers? Sometimes the only way to express a computation Usually lead to compact and efficient code Related operators: - * : can be used in two ways
E N D
Pointers • What is pointer? • A variable (2 or 4 bytes long) that can hold an Address • Why pointers? • Sometimes the only way to express a computation • Usually lead to compact and efficient code • Related operators: - * : can be used in two ways • In declaration : read as pointer, e.g., int *p; • In accessing : read as content of, e.g., x = *p; - & : returns LValue (address) of a variable • Read as address of
70 80 10 20 30 40 ???? 4892 4900 Pointer Examples int x = 70, y = 80, z[4] = {10, 20, 30, 40 }; int *ip; // int pointer ip ip = &x; // ip is assigned to address of x *ip = 200; // content of ip is assigned to 200 y = *ip; // y is assigned to content of ip ip = &z[2]; *ip = *ip + 20; // same as *ip += 20; y = *ip+1; 200 x : 4892 200 51 y : 4894 Z, Z[0] : 4896 Z[1] : 4898 50 Z[2] : 4900 Z[3] : 4902 ip : 4904
Pointer Examples int x = 100; int *p1 = &x; cout << "&x == " << &x << " x == " << x << endl << "p1 == " << p1 << " *p1 == " << *p1 << endl; *p1 += 20; cout << "&x == " << &x << " x == " << x << endl << "p1 == " << p1 << " *p1 == " << *p1 << endl; Output &x == 0x7fff7e60f41c x == 100 p1 == 0x7fff7e60f41c *p1 == 100 &x == 0x7fff7e60f41c x == 120 p1 == 0x7fff7e60f41c *p1 == 120
Pointers in Function arguments void swap_wrong(int x, int y) { int temp; temp = x; x = y; y = temp; } • Arguments are passed by value, thus only a copy is passed. in swap_wrong in swap 10 x: 4397 px: void swap(int *px, int *py) { int temp; temp = *px; *px = *py; *py = temp; } 20 y: 9643 py: temp: temp: in caller: int a = 10, b = 20; swap_wrong(a, b); cout << a << b; swap(&a, &b); cout << a << b; a:4397 10 b:9643 20
pointer Referencing & Dereferencing & * [] variable • Referencing ( & ): create reference (pointer) to memory location • Dereferencing (*, [ ] ): get the content of memory location Note: x = 10; *(&x) = 10;
Pointer Operations • The valid pointer operations are: • Adding or subtracting a pointer and an integer (p i) • Assignment of pointers of the same type (p = q) • Subtracting or comparing two pointers in same array (p - q) • Assigning or comparing to zero. (p = 0) • All other pointer arithmetic are illegal.
1– Addition/Subtraction with int • Used for pointing to different elements in an array int a[6], *pa, x, i; pa = &a[2]; // same as pa = a + 2; *pa pa[0] a[2] *(pa-i) pa[-i] a[2-i] *(pa+i) pa[i] a[2+i] pa-2 pa-1 pa: pa+1 pa+2 pa+3 a: a[0] a[1] a[2] a[3] a[4] a[5] pointer int pointer
Addition/Subtraction with int • Size of the pointed data-type is automatically taken care of. • If address of a pointer (say ptr) is A then address of ptr+i is A+i*sizeof(data-type of ptr) long *lp; int *ip; char *cp; 12 7832 lp7832 *lp= 78563412 12 34 7832 7833 ip7832 *ip=3412 34 7834 56 7833 12 7834 56 7835 78 7832 cp7832 *cp=12 ip+17834 ip[1]=4456 34 7835 44 78 7833 7836 lp+17836 lp[1]= 12345678 7834 56 33 56 7836 7837 ip+27836 ip[2]=5633 cp+27834 cp[2]=56 7835 44 56 7838 34 7837 7839 12
Assignment of Pointers • Pointers of same types can be assigned. float x = 10.5, *p = &x, *q = p; • Pointer to void • is used to hold any type of pointer int *ip; void *vp; vp = ip; // type casting is not essential • Cannot be de-referenced without type casting. int x = *vp; // is illegal type casting is a must int y = *((int *)vp); // is ok
Comparing/Subtraction to Pointer • The resulting type of subtracting two pointers is integer. • Comparison Vs. Subtraction • a < b a – b < 0 • a == b a – b == 0 • a > b a – b > 0 • Compared/Subtracted pointers should point in same array. • Example: /* strlen: return length of string s*/ int strlen(char *s) { char *p = s; while (*p != ‘\0’) p++; return p – s; } pointer - pointer int
Comparing/Assigning to Zero • Zero is the only integer that can be assigned to a pointer • Zero is the only integer that a pointer can be compared to. • Use this to initialize a pointer and to check validity char *m = 0; ... if (m != 0) { ... safe to use the pointer ... } • NULL can be used instead of 0
Pointer Vs Array amessage: now is the time\0 now is the time\0 pmessage: char amessage[] = “now is the time”; // an array char *pmessage = “now is the time”; // a pointer • pmessage is pointer and requires 2/4 bytes for itself • pmessage++ is possible • pmessage=somepointer is legal • amessage is a name for the starting address of the array • amessage++ is illegal • amessage=somepointer is illegal
strcpy example /* strcpy: copy t to s */ void strcpy(char *s, char *t) { int i; i = 0; while ((s[i] = t[i])!=‘\0’) i++; } Note: if you just write s=tthen only the pointer will be copied, not the characters /* strcpy: copy t to s */ void strcpy(char *s, char *t) { while ((*s = *t)!=‘\0’) { s++; t++; } } /* strcpy: copy t to s */ void strcpy(char *s, char *t) { while ((*s++ = *t++)!=‘\0’) ; }
Pointer Vs Array • In function argument array and pointer are same. i.e., following declaration/definition of function are equivalent • int strlen(char *str) • int strlen(char str[ ]) • Arguments are passed by value, thus only a copy is passed. /* strcpy: copy t to s */ void strcpy(char *s, char *t) { while (*s++ = *t++) //DO NOTHING; } ……… char p[25]; char *q = “Hello world”; strcpy(p, q); 4397 s: 9643 t: 4397 p: q: Hello world\0 9643 What is the effect of writing s=t?
strcmp example // strcmp: return <0 if s<t, 0 if s==t, >0 if s>t int strcmp(char *s, char *t) { int i; for (i = 0; s[i] == t[i]; i++) if (s[i] == ‘\0’) return 0; return s[i] – t[i]; } // strcmp: return <0 if s<t, 0 if s==t, >0 if s>t int strcmp(char *s, char *t) { for ( ; *s == *t; s++, t++) if (*s == ‘\0’) return 0; return *s – *t; }
Dynamic Memory Management Program image in RAM Can be accessed via getenv function Environment variables char *gvar = “some string”; int max_size = 200; int myfunc(int x) { int y = 20; x = x + y; return x * y; } int main(void) { int *px = new int; cin >> x; cout << myfunc(x); delete px; } Static Data Stack Heap Program code
Dynamic Memory Allocation // Allocating array int *parr = new int[10]; delete [] parr; // Allocating data for reference class Foo { …………}; Foo *p = new Foo(); p->c1 = ′X′; delete p; // explicit free // Allocating data for reference Foo &r = *new Foo(); r.c1 = ′X′; delete &r; // explicit free
Pointer Anomalies • Uninitialized variable : Before storage can be used, it must be allocated. Foo *p; // forget to initialize pointer with “new” p->c1 = ′R′;// places ′R′ at random location in memory • After storage is no longer needed it must be explicitly deleted otherwise memory leak results. Foo *p = new Foo; p = new Foo; // forgot to free previous storage • After storage is deleted, it must not be used: delete p; p->c1 = ′R′; // result of dereference is undefined • p is called a dangling pointer.
Pointers Vs. Multi-dim Arrays 20 m … • int m[10][20] • mis a 2D array: • 200 int sized locations have been set aside • m[row][col]is calculated as 20row+col • int *pm[10] • pmis a 1D array of pointers to int. • Only 10 pointers are allocated • pm[i] must be initialized/allocated with code (malloc) or static initialized (like name array) • int **ppm • cis a pointer of pointers to int. • Only 1 pointer is allocated • c must be initialized/allocated with code (malloc) • c[i] must be initialized/allocated with code (or static initialized (like name array) • Examples in next slide 10 … … … … pm 10 ppm
Pointers Vs. Multi-dim Arrays 10 11 12 13 20 21 22 23 30 31 32 33 int m[3][4]; for (int r = 0; r < 3; r++) for (int c = 0; c < 4; c++) m[r][c] = (r+1)*10 + c; int *pm[3]; for (int r = 0; r < 3; r++) { pm[r] = new int[4]; for (int c = 0; c < 4; c++) pm[r][c] = (r+1)*10 + c; } int **ppm = new int *[3]; for (int r = 0; r < 3; r++) { ppm[r] = new int[4]; for (int c = 0; c < 4; c++) ppm[r][c] = (r+1)*10 + c; }
0 12 daytab daytab[0] [1] [12] Multi-dimensional Array : Formal Parameters • In function parameter only the left most dimension is unnecessary. • Thus all the following are equivalent: void func(int daytab[2][13]) { … } void func(int daytab[][13]) { … } void func(int (*daytab)[13]) { … } • The brackets in last statement is necessary since [ ] have higher precedence than *. • int (*daytab)[13] : a pointer to an array of 13 elements • int *daytab[13] : an array of 13 pointers to integers.
Complicated Declarations • Read C declarations using a counter-clock wise spiral • Do not cross a bracket (**a[]) unless all the tokens within the bracket are finished int * f () int *f() f is a function returning int * int (*f)() int ( * fp ) () fp is a pointer to function returning int
Complicated Declarations char (*(*x())[5])() [5] char ( * ( * x () ) ) () x is a function returning pointer to array[5] of pointer to function returning char char (*(*x[3])())[5] x is a array[3] of pointer to function returning pointer to array[5] of char
[0] echo\0 [1] hello\0 [2] world\0 [3] 0 Command-line Arguments • main is called with two arguments : • int argc: is the number of command-line arguments • char **argv: pointer to array of strings (i.e., char *) int main(int argc, char **argv) • echo.c invoked with: echo hello world • argc is 3 and argv is argv #include <iostream> int main(intargc, char **argv) { for (int i = 1; i < argc; i++) std::cout << argv[i] << " "; std::cout << endl; }
Command-line Arguments /* Processing command-line options: like –abc –x –v */ int main(int argc, char **argv) { while (--argc > 0 && (*++argv)[0] == ‘-’) { // each option group while (c = *++argv[0]) { // for each option in the goup // process the option } } } find.exe\0 argv (*++argv)[0] ++argv (*++argv) - x f r \0 0 -m\0
Command-line Arguments /* Processing command-line options: like –abc –x –v */ int main(int argc, char **argv) { while (--argc > 0 && (*++argv)[0] == ‘-’) { // each option group while (c = *++argv[0]) { // for each option in the group // process the option } } } find.exe\0 argv ++argv[0] argv[0] - x f r \0 *++argv[0] 0 -m\0
Pointers to Functions • In C/C++, a function itself is not a variable • But pointer to function can be created • int (*comp)(void *, void *); • comp is a pointer to function that returns int and takes two void * type arguments • BEWARE: int *comp(void *, void *) • means that comp is a function that that returns int * and takes two void * type arguments • int result = (*comp)(&x, &y) • invokes comp with parameters x and y
Be Careful with * and ++/-- • * and ++ / -- are executed from right to left char *p = “XAD”; char *q = p; char c; The above is also true for the – – operator.
Coercion: Storage of Values in Memory long int • Same memory location can be interpreted in different ways: Intrepreted as 1 long int 41 43 45 47 0x41434547 short int 47 7832 Intrepreted as 2 short int 45 47 0x4547 45 7833 41 43 0x4143 7834 43 7835 41 char 47 ‘G’ Intrepreted as 4 char 4-bytes in RAM 45 ‘E’ Note: All numbers in this slide are in hexadecimal system. 43 ‘C’ Higher bits stored in higher address 41 ‘A’
Coercion: Assignment of Pointers • Cast and then assign int i = 0x4145, *ip = &i; char *cp = (char *)ip; cout << *cp << endl << cp[1] << endl << showbase << hex << int (*cp) << endl << int (cp[1]) << endl << *ip << endl ; cp:8996 E *cp: 78 38 A *(cp+1): hi-8bits[7839] lo-8bits[7838] Logical View 45 i:7838 41 78 38 41 45 7839 *ip: ip:8976 RAM bytes
lp:8974 78 32 47 l:7832 78 32 ip:8976 45 7833 78 32 cp:8978 43 7834 41 7835 RAM bytes Coercion: Assignment of Pointers • Cast and then assign long int l = 0x41434547, *lp = &l; int *ip = (int *)lp; // same as int *ip = (int *)&l; char *cp = (char *)lp; // same as char *ip = (char *)&l; Note: lp, ip and cp are all of size 2 bytes though they are pointing to data of different sizes, 4, 2 and 1 bytes, respectively.
47 *cp=‘G’ 47 7832 47 7832 7832 *ip 0x4547 45 *(cp+1) =‘E’ 45 7833 45 7833 7833 *lp 0x41434547 43 *(cp+2) =‘C’ 43 7834 7834 43 7834 *(ip+1) 0x4143 41 *(cp+3) =‘A’ 41 7835 7835 41 7835 RAM bytes RAM bytes RAM bytes Coercion: Assignment of Pointers • Cast and then assign long int l = 0x41434547, *lp = &l; int *ip = (int *)lp; char *cp = (char *)lp; cout << *cp << *(cp+1) << *(cp+2) << *(cp+3) << *ip << *(ip+1) << *lp;