490 likes | 982 Views
Pointers. Declaring, dereferencing, & assigning Call by value & reference Constant pointers Arrays (arithmetic, strings, pointers) Pointers to functions Command line arguments. Pointers. Pointers – variables that contain a memory address of another variable as its value
E N D
Pointers • Declaring, dereferencing, & assigning • Call by value & reference • Constant pointers • Arrays (arithmetic, strings, pointers) • Pointers to functions • Command line arguments
Pointers • Pointers – variables that contain a memory address of another variable as its value • What are they good for? • Generic access to several similar variables • Call by reference function parameters • Dynamically allocated data structures • Creating copies of arrays and structures
Terminology • & operator – address operator • Returns the address of its operand • * operator – indirection or dereferencing operator • Returns the value of the object to which its operand points
Terminology • Declaring a variable int num = 5; • Declaring a pointer int *nptr = 0; • Assigning an address to a pointer nptr = # • Dereferencing a pointer printf("%d",*nptr);
Assigning an Address int num = 5; int *nptr = NULL; /*defined in .h files*/ nptr = # /*assign num's address to nptr*/ printf("num=%d &num=%p \n",num,&num); /* num=5 &num=0x244ff44*/ printf("*nptr=%d nptr=%p \n",*nptr,nptr); /* *nptr=5 nptr=0x244ff44*/
Equivalent Code • int num = 10, *ptr = # • int num = 10; int *ptr = 0; ptr = #
Dereferencing Pointers • With pointers, you can alter the value that the pointer is pointing to: int num=10, *nptr=# ++*nptr; /*unary operators associate*/ (*nptr)++; /*right to left*/ printf(" num=%d &num=%p\n",num,&num); printf("*nptr=%d nptr=%p\n",*nptr,nptr); /* num=12 &num=0x244ff44 *nptr=12 nptr=0x244ff44 */
Dereferencing Pointers • Can also alter the actual pointer value, which may create an error: int x=3, num=6, y=9, *nptr=# nptr++; printf(" num=%d &num=%p\n",num,&num); printf("*nptr=%d nptr=%p\n",*nptr,nptr); /* num=6 &num=ffbefb40 *nptr=3 nptr=ffbefb44 */
Assigning Pointers to Pointers • Must be of the same type • If not, must use a cast operator • Exception is type void • Generic pointer • Can be assigned to any pointer type • Any pointer type can be assigned to it • Cannot be dereferenced (must cast it first)
Dereferencing Pointers • The compiler must know the data type to know how to dereference a pointer • For integer pointers, the compiler knows that it refers to 4-bytes in memory • Since a void pointer can be any data type, the compiler cannot dereference it
Assigning Pointers to Pointers int num = 1234567890; /*0x499602D2*/ char ch = 'A'; int *iptr = # char *cptr = &ch; iptr = (int *)cptr; /*cast char pointer to integer pointer*/ printf("*iptr=%c\n",*iptr); /* *iptr=A (no data lost)*/ iptr = # cptr = (char *)iptr; /*cast integer pointer to char pointer*/ printf("*cptr=%d\n",*cptr); /* *cptr=-46 (loss of data)*/ /*0x499602D2 => D2 => 1101 0010 => -46*/
Generic Pointer - void * int num = 1234567890; char ch = 'A'; int *iptr = # char *cptr = &ch; void *vptr = NULL; vptr = iptr; printf(“*vptr=%d\n",*((int *)vptr)); /* *vptr=1234567890 */ /* cast void to int pointer*/ vptr = cptr; printf(“*vptr=%c\n",*((char *)vptr)); /* *vptr=A */ /* cast void to a char pointer*/
Call by Value • Changing the argument in the function does not change the original variable void swap1(int, int); . . . int num1=3, num2=7; swap1(num1,num2); printf("num1=%d num2=%d\n",num1,num2); . . . /*num1=3 num2=7*/ void swap1(int a, int b){ int temp = a; a=b; b=temp;}
Call by Reference • Changing the argument in the function does change the original variable void swap2(int *, int *); . . . int num1=3, num2=7; swap2(&num1,&num2); printf("num1=%d num2=%d\n",num1,num2); . . . /* num1=7 num2=3 */ void swap2(int *a, int *b){ int temp = *a; *a=*b; *b=temp;}
Call by Reference • Another version – arguments are pointers void swap2(int *, int *); . . . int num1=3, *p1=&num1, num2=7, *p2=&num2; swap2(p1,p2); printf("num1=%d num2=%d\n",num1,num2); . . . /* num1=7 num2=3 */ void swap2(int *a, int *b){ int temp = *a; *a=*b; *b=temp;}
Class Exercise 1 #include <stdio.h> void funA(void *, int); int main(){ int a = 10, b = 20, c = 30; int *ptr1 = &a, *ptr2 = &b, *ptr3 = &c; ptr3 = ptr2; b++; (*ptr3)++; c = *ptr3; funA(ptr1, *ptr2); printf("%d %d %d\n",a,b,c); return 0; } void funA(void *a, int b){ int temp = *((int *)a); *((int *)a) = b; b = temp; }
Constant Pointers int num1 = 3; int num2 = 7; int *const ptr1 = &num1; /*cannot change address in ptr1*/ int *ptr2 = &num2; num1++; /*no warning*/ (*ptr1)++; /*no warning*/ ptr1 = ptr2; /*gives warning*/
Constant Pointers int num1 = 3, num2 = 7; const int *const ptr1 = &num1; /*cannot change address and cannot change value at that address*/ int *ptr2 = &num2; num1++; /*no warning*/ (*ptr1)++; /*gives warning*/ ptr1 = ptr2; /*gives warning*/
Constant Pointers in Functions void swap2(const int *a, const int *b){ /*cannot change value at that address*/ int temp = *a; /*no warning*/ *a=*b; /*gives warning*/ *b=temp; /*gives warning*/ }
Pointers & Arrays • In C, almost interchangeable • An array name can be thought of as a constant pointer • An array name is an address • Pointers can be used to do array subscripting • A pointer stores an address
Pointers & Arrays int array[] = {1,2,3,4}; int *ptr = NULL; ptr = array; ptr = &array[0]; /*same as line above*/ printf("array[0] = %d\n",array[0]); printf("*(array+1)= %d\n",*(array+1)); printf("ptr[2] = %d\n",ptr[2]); printf("*(ptr+3) = %d\n",*(ptr+3)); /* array[0] = 1 *(array+1)= 2 ptr[2] = 3 *(ptr+3) = 4 */
Alternative Array Loop int array[] = {1,2,3,4}; int *ptr = NULL; ptr = array; while(ptr!=(array+4)){ printf("%p = %d\n",ptr,*ptr); ptr++; } 0x257fc80 = 1 0x257fc84 = 2 0x257fc88 = 3 0x257fc8c = 4
How are arrays stored? int in[]={1,2,3,4}; char ch[]={'a','b','c','d'}; int i=0; for(i=0;i<4;i++) printf("in[%d] = %p ch[%d] = %p\n",i,&in[i],i,&ch[i]); /* in[0] = 0x244ff30 ch[0] = 0x244ff2c in[1] = 0x244ff34 ch[1] = 0x244ff2d in[2] = 0x244ff38 ch[2] = 0x244ff2e in[3] = 0x244ff3c ch[3] = 0x244ff2f */
Class Exercise 2 • What’s the output of the following code? • See exercise2.txt
Pointer Arithmetic • Valid pointer operations • Assignment of pointers of the same type • Adding or subtracting a pointer & an integer • Comparing pointers of the same array • Assigning or comparing to zero • Invalid pointer operations • Add two pointers • Multiply, divide, shift, or and a pointer • Add float or double to a pointer • Assign pointers of different types without a cast
/*Pointer Arithmetic*/ int i[] = {10,20,30,40}, *ip=i; ip+=3; /* 3*4=12 bytes */ printf(" i=%p *i=%d\n",i,*i); printf("ip=%p *ip=%d\n",ip,*ip); /* i=ffbefb38 *i=10 ip=ffbefb44 *ip=40 */
/*Pointer Arithmetic*/ double d[] = {1.1, 2.2, 3.3, 4.4}, *dp=d; dp+=3; /* 3*8=24 bytes */ printf(" d=%p *d=%.1f\n",d,*d); printf("dp=%p *dp=%.1f\n",dp,*dp); /* d=ffbefb10 *d=1.1 dp=ffbefb28 *dp=4.4*/
Character Pointers • char array[] = "this is an array"; • Array of characters + '\0' • Can change the characters in the array • Cannot change the array’s address • char *ptr = "this is a pointer"; • Points to constant characters + '\0' • Cannot change the string constant • Can change the pointer value
Character Pointers #include <stdio.h> int main(){ char a[] = "character array"; char *b = "constant array"; a=b; /*compiler error: incompatible types in assignment*/ a[0]='C'; b[0]='A'; /*runtime error: Segmentation Fault*/ return 0; }
String Copy • Must be careful when copying strings • Should copy each character to new string • Will create two different strings • Should not simply assign a new address • Will have two pointers pointing to the same string
Bad String Copy #include <stdio.h> int main(){ char a[] = "character array"; char *b; b=a; b[0]='Z'; printf("%s\n",a); /*Zharacter array*/ printf("%s\n",b); /*Zharacter array*/ return 0; }
Good String Copy #include <stdio.h> int main(){ char a[] = "character array"; char b[] = " "; char *ptr1 = a, *ptr2 = b; while(*ptr1!='\0') *ptr2++=*ptr1++; *ptr2='\0'; /*while(*ptr2++=*ptr1++);*/ b[0]='Z'; printf("%s\n",a); /*character array*/ printf("%s\n",b); /*Zharacter array*/ }
Arrays of Pointers • Arrays can contain pointers • Common use is to have an array of strings const char *array[]={"zero","one","two"}; /*adds null character ('\0') to end*/ printf("%s\n",array[1]); /*one*/ printf("%s\n",*(array+1)); /*one*/ printf("%c\n",array[2][1]); /*w*/ printf("%c\n",*(*(array+2)+1)); /*w*/ if('\0'==array[0][4]) printf("true\n"); /*true*/
Pointers to Functions • A pointer can also store the address of a function • A function name is the address in memory of the start of the function • Function pointers can be • Passed to a function • Returned to functions • Stored in arrays • Assigned to other function pointers
An Array of Pointers to Functions #include <stdio.h> void fun1(void); void fun2(void); void fun3(void); int main(){ void (*array[3])(void) = {fun1,fun2,fun3}; /*declare an array of pointers to functions*/ int i; for (i=0;i<3;i++) (*array[i])();/*make a function call*/ return 0; /*output: 1st 2nd 3rd */ } void fun1(void){printf("1st ");} void fun2(void){printf("2nd ");} void fun3(void){printf("3rd ");}
Alternative Code #include <stdio.h> void fun1(void); void fun2(void); void fun3(void); int main(){ void (*array[3])(void) = {fun1,fun2,fun3}; /*declare an array of pointers to functions*/ int i; for (i=0;i<3;i++) array[i](); /*or (*array[i])(); */ return 0; /*output: 1st 2nd 3rd */ } void fun1(void){printf("1st ");} void fun2(void){printf("2nd ");} void fun3(void){printf("3rd ");}
Pointers to Functions void(*array[3])(void)={fun1,fun2,fun3}; • “array” is an array of 3 pointers to 3 functions with no arguments and return type void (*array[i])(void); array[i](); • The function is dereferenced and no arguments are passed to it
An Array of Pointers to Functions II #include <stdio.h> int fun1(int); int fun2(int); int fun3(int); int main(){ int (*array[3])(int) = {fun1,fun2,fun3}; int i; for (i=0;i<3;i++) printf("%d ",(*array[i])(i)); /*1 3 5*/ /* printf("%d ", array[i](i)); */ return 0; } int fun1(intx){return x+1;} int fun2(intx){return x+2;} int fun3(intx){return x+3;}
Pointers to Functions II int(*array[3])(int)={fun1,fun2,fun3}; • “array” is an array of 3 pointers to 3 functions with one int argument and return type int (*array[i])(i); array[i](i); • The function is dereferenced and integer “i” is passed as an argument to the function
Passing Function Pointers to Functions #include <stdio.h> void fun1(int (*)(), float (*)()); int fun2(); float fun3(); int main(){ fun1(fun2,fun3); /*f1=12 f2=1.234000*/ return 0; } void fun1(int (*f1)(),float (*f2)()){ printf("f1=%d f2=%f", f1(), f2()); } int fun2(){return 12;} float fun3(){return 1.234;}
Passing Function Pointers void fun1(int (*)(), float (*)()); • “Fun1” is a function of return type void, that takes two arguments –a function pointer that returns an integer with no arguments,and a function pointer that returns a float with no arguments
Passing Function Pointers fun1(fun2,fun3); • “fun1” is dereferenced with pointers to fun2 &fun3as arguments void fun1(int (*f1)(),float (*f2)()) • f1& f2 hold the addresses of fun2 & fun3
Class Exercise 3 #include <stdio.h> void fun1(int(*)(int, int), float (*) (float, float)); int fun2(int,int); float fun3(float,float); int main(){ fun1(fun2,fun3); return 0; } void fun1(int (*f1)(int, int), float (*f2)(float, float)){ printf("f1=%d f2=%f", f1(6, 5), f2(1.5, 0.3));} int fun2(int a, int b){return a*b;} float fun3(float a, float b){return a/b;}
Textbook Examples • Pointers to functions • Ascending or descending bubblesort • See bubble.c • Used in menu-driven system • See menu.c
Class Exercise 4 #include <stdio.h> char *funA(char *); int main(){ char str[]="string"; char *cptr = funA(str); printf("%s\n",cptr); return 0; } char *funA(char *ch){ ch+=3; return ch; }
Command-line Arguments int main(int argc, char *argv[]) • argc – “argument count” is number of command-line arguments the program was invoked with • argv – “argument vector” is a pointer to an array of character strings that contain the arguments
Command-line Arguments int main(int argc, char *argv[]) • Can call these anything int main(int foo, char *bar[]) • Can also write *argv[] as **argv • a pointer to a pointer to a character
Command-line Arguments /*Will repeat 1st line of text*/ #include <stdio.h> int main(int argc, char *argv[]){ int i=0; for(i=0;i<argc;i++) printf("%s ",argv[i]); printf("\n"); return 0; } /*See command.txt*/
Program on UNIX • uhunix2: a.out* one two three • a.out one two three • uhunix2: a.out* one two <three • a.out one two