Pointers and Addresses Pointer – A pointer is a variable that contains the address of a variable Address Operator & – &x is the address of the variable x Indirection or Dereferencing Operator * – *p access the object the pointer p points to A first example main() { int x = 1; int *p; p = &x; printf(“%d”, *p); } … … … FF00 p &p F000 &x x 1 *p F000 0000 FFFF variables addresses name name value value Full Memory Diagram (with name and value for the variables and addresses)
Pointers and Arrays a The name of this array is “a” and its value is equivalent to the address of its first element: &a[0]. a+2 p+3 a+i points to the i-th element beyond a. p+i points to the i-th element beyond p. As p is a variable, p=a or ++p are legal; but as an array name is not a variable, expression like a=p or ++a are illegal ! p int *p=a; a[3] a[1] a[0] a[2] int a[4]; The declaration int a[4]; defines an array of size 4, that is, a block of 4 consecutive objects of type int, named a[0], a[1], a[2], a[3].
Pointers and Functions • Pointers can be used to pass addresses of variables to called functions, thus allowing the called function to alter the values stored there. • We looked earlier at a swap function that did not change the values stored in the main program because only the values were passed to the function swap. • This is known as "call by value". • If instead of passing the values of the variables to the called function, we pass their addresses, so that the called function can change the values stored in the calling routine. This is known as "call by reference" since we are referencing the variables. • The following shows the swap function modified from a "call by value" to a "call by reference". Note that the values are now actually swapped when the control is returned to main function.
Pointers with Functions (example) #include <stdio.h> void swap ( int *a, int *b ) ; int main ( ) { int a = 5, b = 6; printf("a=%d b=%dn",a,b) ; swap (&a, &b) ; printf("a=%d b=%dn",a,b) ; return 0 ; } void swap( int *a, int *b ) { int temp; temp= *a; *a= *b; *b = temp ; printf ("a=%d b=%dn", *a, *b); } Results: a=5 b=6 a=6 b=5 a=6 b=5
Arithmetic and Logical Operations on Pointers • A pointer may be incremented or decremented • An integer may be added to or subtracted from a pointer. • Pointer variables may be subtracted from one another. • Pointer variables can be used in comparisons, but usually only in a comparison to NULL. • When an integer is added to or subtracted from a pointer, the new pointer value is changed by the integer times the number of bytes in the data variable the pointer is pointing to. • For example, if the pointer valptr contains the address of a double precision variable and that address is 234567870, then the statement: valptr = valptr + 2; would change valptr to 234567886
2D Arrays and Pointers Example #include <stdio.h> void main(void){ int array[3][4],i,j,val=0; for(i=0;i < 3; i++) for(j=0; j < 4; j++) { array[i][j] = val++; printf("array[%d][%d]: %dn",i,j,array[i][j]); } printf("array: %xn",array); printf("array[0]: %xn",array[0]); printf("array[1]: %xn",array[1]); printf("*array[1]: %dn",*array[1]); printf("*array+1: %xn",*array+1); printf("*array[2]: %dn",*array[2]); printf("*array+2: %xn",*array+2); printf("**array+2: %dn",**array+2); printf("*(*(array+1)+2): %dn",*(*(array+1)+2)); printf("*(array+1)+2: %xn",*(array+1)+2); printf("*array[3]: %xn",*array[3]); } array[0][0]: 0 array[0][1]: 1 array[0][2]: 2 array[0][3]: 3 array[1][0]: 4 array[1][1]: 5 array[1][2]: 6 array[1][3]: 7 array[2][0]: 8 array[2][1]: 9 array[2][2]: 10 array[2][3]: 11 array: effff804 array[0]: effff804 array[1]: effff814 *array[1]: 4 *array+1: effff808 *array[2]: 8 *array+2: effff80c **array+2: 2 *(*(array+1)+2): 6 *(array+1)+2: effff81c *array[3]: 0
Character Pointers and Functions • The following calls will work: // return length of string s int strlen(char s[]) { int n; for (n = 0; *s != '0'; s++) n++; return n; } That means, as a formal parameter in a function definition, char s[] and char *s are equivalent. Within the called function, this array name is a local pointer variable! When an array name is passed to a function, what is passed is the location of the first element. strlen("hello world"); // string constant !! strlen(a); // char a[10]; strlen(p); // char *p;
A Test Program #include <stdio.h> /* Return length of string s */ int strlen(char s[]) { int n; for (n = 0; *s != '0'; s++) n++; return n; } main() { int i1, i2, i3; char a[] = "hello"; char *p = a; i1 = strlen(a); i2 = strlen(p); i3 = strlen("hello"); } •'0' • 'o' • 'l' • 'l' • 'e' • 'h' p a
Casting Pointers When assigning a memory address of a variable of one type to a pointer that points to another type it is best to use the cast operator to indicate the cast is intentional (this will remove the warning) Example: int V = 101; float *P = (float *) &V; /* Casts int address to float * */ Removes warning, but is still a somewhat unsafe thing to do The General (void) Pointer A void * is considered to be a general pointer No cast is needed to assign an address to a void * or from a void * to another pointer type Example: int V = 101; void *G = &V; /* No warning */ float *P = G; /* No warning, still not safe */ Certain library functions return void * results (more later)
NULL Pointer • If wish to have a pointer that points to “nowhere”, should make this explicit by assigning it to NULL. double *pval1 = NULL; double *pval2 = 0; • The integer constants 0 and 0L are valid alternatives to NULL, but the symbolic constant is (arguably) more readable. const Pointers • A pointer may be declared const in two different ways. • First, and most commonly: int i = 5, j = 6; const int *p = &i; *p = j; /* Invalid.Cannot change i via p. */ • Can change what it points to but cannot change the value of the object it points to. int i = 5, j = 6; const int *p = &i; p = &j; /* Valid. p now points to j. */ *p = i; /* Invalid. Cannot change j via p. */
• Second form: int i = 5, j = 6; int * const p = &i; *p = j; /* Valid. i is now 6 */ p = &j; /* Invalid. p must always point to i. */ • Can change value of pointed-to object, but pointer must always refer to the same address. • Possible to combine the two forms: int i = 5, j = 6; const int * const p = &i; *p = j; /* Invalid. i cannot be changed via p. */ p = &j; /* Invalid. p must always point to i. */ • The first form turns out to be useful for passing objects to functions when using “pass-by-reference” semantics.
Pointers to Pointers A pointer can also be made to point to a pointer variable (but the pointer must be of a type that allows it to point to a pointer) #include <stdio.h> int main(void) { int i = 16; int *p = &i; int **pp; pp = &p; printf("%in", **pp); return 0; } p i 16 0x2320 0x2320 0x2324 pp 0x2324 0x2328 pp is a “pointer to” a “pointer to an int”
int main(void) { int i = 10, j = 7, k; int *p = &i; int *q = &j; int *pp = &p; **pp += 1; *pp = &k; **pp = *q; i = *q***pp; i = *q/**pp; /* headache? */; return 0; } p i pp j k q
Array of pointers (Pointer Arrays) • Just like we have an array of data types, we can have an array of pointers. • Declaration: – char *names[10]; // array of 10 character pointers. – Each element of the array is a pointer to a data type (in this case character). • names [0] is a character pointer ……. • More examples: – int *d [10] ; // array of 10 integer pointers. – float *f [23]; // array of 23 float pointers. – double *d [5]; // array of 5 double pointers. # include <stdio.h> int main () { char *test[5] = {"James", "Nat", "Pat", "Quinn", "Joe"}; }
char *month_name(int n) { static char *name[] = { "Illegal month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; return (n<1 || n>12)? name[0]: name[n]; } • A block of memory (probably in the constant area) is initialized like this: Illegal month0January0February0 March0April0May0June0July0August0 September0October0November0December0
Arrays of Pointers • The pointers are initialized like so Illegal month0January0February0 March0April0May0June0July0August0 September0October0November0December0
Function pointers in C • Functions exist in memory just like variables – C will allow you to define pointers to functions just like variables – 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 /* first declare the function */ double ari (int a, int b){ return (a+b)/2.0; } /* now declare the function pointer */ double (*p_func)(int, int); /*Assigning an address to a function pointer*/ p_func = &ari; /* assignment using address */ /* Calling a function using a function pointer*/ res = (*p_func)(3,12); /* explicit dereferencing */
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 ");}
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;} 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
Declarations Examples int A A is a int float B [5] B is a 1D array of size 5 of floats int * C C is a pointer to an int char D [6][3] D is a 2D array of size 6,3 of chars int * E [5] E is a 1D array of size 5 of pointers to ints int (* F) [5] F is a pointer to a 1D array of size 5 of ints int G (…) G is a function returning an int char * H (…) H is a function returning a pointer to a char
Arguments to main () • Command line arguments are parameters supplied to a program, when the program is invoked. cc myfile.c cc xyz.c -lm netscape www.mailcity.com average 10 20 30 40 50 • How do these parameters get into the program? – Every C program has a main function. – main can take two arguments conventionally called argc and argv. – Information regarding command line arguments are passed to the program through argc and argv.
Echoing the command line arguments int main (int argc, char *argv[]) { int i; printf (“argc = %dn”, argc) ; for (i=0; i<argc; ++i) printf (“argv[%d] = %sn”, i,argv[i]) ; return 0; } C:> p1 how many argc = 3 argv[0] = p1 argv[1] = how argv[2] = many

C Programming for Problem Solving programming Unit- 3

  • 1.
    Pointers and Addresses Pointer –A pointer is a variable that contains the address of a variable Address Operator & – &x is the address of the variable x Indirection or Dereferencing Operator * – *p access the object the pointer p points to A first example main() { int x = 1; int *p; p = &x; printf(“%d”, *p); } … … … FF00 p &p F000 &x x 1 *p F000 0000 FFFF variables addresses name name value value Full Memory Diagram (with name and value for the variables and addresses)
  • 2.
    Pointers and Arrays a Thename of this array is “a” and its value is equivalent to the address of its first element: &a[0]. a+2 p+3 a+i points to the i-th element beyond a. p+i points to the i-th element beyond p. As p is a variable, p=a or ++p are legal; but as an array name is not a variable, expression like a=p or ++a are illegal ! p int *p=a; a[3] a[1] a[0] a[2] int a[4]; The declaration int a[4]; defines an array of size 4, that is, a block of 4 consecutive objects of type int, named a[0], a[1], a[2], a[3].
  • 3.
    Pointers and Functions •Pointers can be used to pass addresses of variables to called functions, thus allowing the called function to alter the values stored there. • We looked earlier at a swap function that did not change the values stored in the main program because only the values were passed to the function swap. • This is known as "call by value". • If instead of passing the values of the variables to the called function, we pass their addresses, so that the called function can change the values stored in the calling routine. This is known as "call by reference" since we are referencing the variables. • The following shows the swap function modified from a "call by value" to a "call by reference". Note that the values are now actually swapped when the control is returned to main function.
  • 4.
    Pointers with Functions(example) #include <stdio.h> void swap ( int *a, int *b ) ; int main ( ) { int a = 5, b = 6; printf("a=%d b=%dn",a,b) ; swap (&a, &b) ; printf("a=%d b=%dn",a,b) ; return 0 ; } void swap( int *a, int *b ) { int temp; temp= *a; *a= *b; *b = temp ; printf ("a=%d b=%dn", *a, *b); } Results: a=5 b=6 a=6 b=5 a=6 b=5
  • 5.
    Arithmetic and LogicalOperations on Pointers • A pointer may be incremented or decremented • An integer may be added to or subtracted from a pointer. • Pointer variables may be subtracted from one another. • Pointer variables can be used in comparisons, but usually only in a comparison to NULL. • When an integer is added to or subtracted from a pointer, the new pointer value is changed by the integer times the number of bytes in the data variable the pointer is pointing to. • For example, if the pointer valptr contains the address of a double precision variable and that address is 234567870, then the statement: valptr = valptr + 2; would change valptr to 234567886
  • 6.
    2D Arrays andPointers Example #include <stdio.h> void main(void){ int array[3][4],i,j,val=0; for(i=0;i < 3; i++) for(j=0; j < 4; j++) { array[i][j] = val++; printf("array[%d][%d]: %dn",i,j,array[i][j]); } printf("array: %xn",array); printf("array[0]: %xn",array[0]); printf("array[1]: %xn",array[1]); printf("*array[1]: %dn",*array[1]); printf("*array+1: %xn",*array+1); printf("*array[2]: %dn",*array[2]); printf("*array+2: %xn",*array+2); printf("**array+2: %dn",**array+2); printf("*(*(array+1)+2): %dn",*(*(array+1)+2)); printf("*(array+1)+2: %xn",*(array+1)+2); printf("*array[3]: %xn",*array[3]); } array[0][0]: 0 array[0][1]: 1 array[0][2]: 2 array[0][3]: 3 array[1][0]: 4 array[1][1]: 5 array[1][2]: 6 array[1][3]: 7 array[2][0]: 8 array[2][1]: 9 array[2][2]: 10 array[2][3]: 11 array: effff804 array[0]: effff804 array[1]: effff814 *array[1]: 4 *array+1: effff808 *array[2]: 8 *array+2: effff80c **array+2: 2 *(*(array+1)+2): 6 *(array+1)+2: effff81c *array[3]: 0
  • 7.
    Character Pointers andFunctions • The following calls will work: // return length of string s int strlen(char s[]) { int n; for (n = 0; *s != '0'; s++) n++; return n; } That means, as a formal parameter in a function definition, char s[] and char *s are equivalent. Within the called function, this array name is a local pointer variable! When an array name is passed to a function, what is passed is the location of the first element. strlen("hello world"); // string constant !! strlen(a); // char a[10]; strlen(p); // char *p;
  • 8.
    A Test Program #include<stdio.h> /* Return length of string s */ int strlen(char s[]) { int n; for (n = 0; *s != '0'; s++) n++; return n; } main() { int i1, i2, i3; char a[] = "hello"; char *p = a; i1 = strlen(a); i2 = strlen(p); i3 = strlen("hello"); } •'0' • 'o' • 'l' • 'l' • 'e' • 'h' p a
  • 9.
    Casting Pointers When assigninga memory address of a variable of one type to a pointer that points to another type it is best to use the cast operator to indicate the cast is intentional (this will remove the warning) Example: int V = 101; float *P = (float *) &V; /* Casts int address to float * */ Removes warning, but is still a somewhat unsafe thing to do The General (void) Pointer A void * is considered to be a general pointer No cast is needed to assign an address to a void * or from a void * to another pointer type Example: int V = 101; void *G = &V; /* No warning */ float *P = G; /* No warning, still not safe */ Certain library functions return void * results (more later)
  • 10.
    NULL Pointer • Ifwish to have a pointer that points to “nowhere”, should make this explicit by assigning it to NULL. double *pval1 = NULL; double *pval2 = 0; • The integer constants 0 and 0L are valid alternatives to NULL, but the symbolic constant is (arguably) more readable. const Pointers • A pointer may be declared const in two different ways. • First, and most commonly: int i = 5, j = 6; const int *p = &i; *p = j; /* Invalid.Cannot change i via p. */ • Can change what it points to but cannot change the value of the object it points to. int i = 5, j = 6; const int *p = &i; p = &j; /* Valid. p now points to j. */ *p = i; /* Invalid. Cannot change j via p. */
  • 11.
    • Second form: inti = 5, j = 6; int * const p = &i; *p = j; /* Valid. i is now 6 */ p = &j; /* Invalid. p must always point to i. */ • Can change value of pointed-to object, but pointer must always refer to the same address. • Possible to combine the two forms: int i = 5, j = 6; const int * const p = &i; *p = j; /* Invalid. i cannot be changed via p. */ p = &j; /* Invalid. p must always point to i. */ • The first form turns out to be useful for passing objects to functions when using “pass-by-reference” semantics.
  • 12.
    Pointers to Pointers Apointer can also be made to point to a pointer variable (but the pointer must be of a type that allows it to point to a pointer) #include <stdio.h> int main(void) { int i = 16; int *p = &i; int **pp; pp = &p; printf("%in", **pp); return 0; } p i 16 0x2320 0x2320 0x2324 pp 0x2324 0x2328 pp is a “pointer to” a “pointer to an int”
  • 13.
    int main(void) { int i= 10, j = 7, k; int *p = &i; int *q = &j; int *pp = &p; **pp += 1; *pp = &k; **pp = *q; i = *q***pp; i = *q/**pp; /* headache? */; return 0; } p i pp j k q
  • 14.
    Array of pointers(Pointer Arrays) • Just like we have an array of data types, we can have an array of pointers. • Declaration: – char *names[10]; // array of 10 character pointers. – Each element of the array is a pointer to a data type (in this case character). • names [0] is a character pointer ……. • More examples: – int *d [10] ; // array of 10 integer pointers. – float *f [23]; // array of 23 float pointers. – double *d [5]; // array of 5 double pointers. # include <stdio.h> int main () { char *test[5] = {"James", "Nat", "Pat", "Quinn", "Joe"}; }
  • 15.
    char *month_name(int n) { staticchar *name[] = { "Illegal month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; return (n<1 || n>12)? name[0]: name[n]; } • A block of memory (probably in the constant area) is initialized like this: Illegal month0January0February0 March0April0May0June0July0August0 September0October0November0December0
  • 16.
    Arrays of Pointers •The pointers are initialized like so Illegal month0January0February0 March0April0May0June0July0August0 September0October0November0December0
  • 17.
    Function pointers inC • Functions exist in memory just like variables – C will allow you to define pointers to functions just like variables – 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 /* first declare the function */ double ari (int a, int b){ return (a+b)/2.0; } /* now declare the function pointer */ double (*p_func)(int, int); /*Assigning an address to a function pointer*/ p_func = &ari; /* assignment using address */ /* Calling a function using a function pointer*/ res = (*p_func)(3,12); /* explicit dereferencing */
  • 18.
    An Array ofPointers 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 ");}
  • 19.
    Passing Function Pointersto 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;} 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
  • 20.
    Declarations Examples int AA is a int float B [5] B is a 1D array of size 5 of floats int * C C is a pointer to an int char D [6][3] D is a 2D array of size 6,3 of chars int * E [5] E is a 1D array of size 5 of pointers to ints int (* F) [5] F is a pointer to a 1D array of size 5 of ints int G (…) G is a function returning an int char * H (…) H is a function returning a pointer to a char
  • 21.
    Arguments to main() • Command line arguments are parameters supplied to a program, when the program is invoked. cc myfile.c cc xyz.c -lm netscape www.mailcity.com average 10 20 30 40 50 • How do these parameters get into the program? – Every C program has a main function. – main can take two arguments conventionally called argc and argv. – Information regarding command line arguments are passed to the program through argc and argv.
  • 22.
    Echoing the commandline arguments int main (int argc, char *argv[]) { int i; printf (“argc = %dn”, argc) ; for (i=0; i<argc; ++i) printf (“argv[%d] = %sn”, i,argv[i]) ; return 0; } C:> p1 how many argc = 3 argv[0] = p1 argv[1] = how argv[2] = many