Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 22

Pointers and Addresses

Pointer
variables addresses
– A pointer is a variable that
contains the address of a variable name value value name
Address Operator & 0000
– &x is the address of the variable x …
Indirection or Dereferencing
*p x 1 F000 &x
Operator * …
– *p access the object the pointer p
points to p F000 FF00 &p

A first example
FFFF
main()
{
Full Memory Diagram
int x = 1;
(with name and value
int *p; for the variables and
addresses)
p = &x;
printf(“%d”, *p);
}
Pointers and Arrays

The declaration int a[4]; a


defines an array of size 4,
a[0]
that is, a block of 4
a[1] a+2
consecutive objects of type a[2]
int, named a[0], a[1], a[3]
a[2], a[3]. p+3
The name of this array is
p
“a” and its value is
equivalent to the address of
its first element: &a[0]. int a[4];
int *p=a;
points to the i-th element beyond a.
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
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 )


void swap ( int *a, int *b ) ; {
int main ( ) int temp;
{ temp= *a; *a= *b; *b = temp ;
int a = 5, b = 6; printf ("a=%d b=%d\n", *a, *b);
printf("a=%d b=%d\n",a,b) ; }
swap (&a, &b) ; Results:
printf("a=%d b=%d\n",a,b) ; a=5 b=6
return 0 ; 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 array[0][0]: 0
array[0][1]: 1
#include <stdio.h>
array[0][2]: 2
void main(void){
array[0][3]: 3
int array[3][4],i,j,val=0;
for(i=0;i < 3; i++) array[1][0]: 4
for(j=0; j < 4; j++) array[1][1]: 5
{ array[1][2]: 6
array[i][j] = val++; array[1][3]: 7
printf("array[%d][%d]: %d\n",i,j,array[i][j]); array[2][0]: 8
} array[2][1]: 9
printf("array: %x\n",array); array[2][2]: 10
printf("array[0]: %x\n",array[0]); array[2][3]: 11
printf("array[1]: %x\n",array[1]); array: effff804
printf("*array[1]: %d\n",*array[1]); array[0]: effff804
printf("*array+1: %x\n",*array+1); array[1]: effff814
printf("*array[2]: %d\n",*array[2]); *array[1]: 4
printf("*array+2: %x\n",*array+2); *array+1: effff808
printf("**array+2: %d\n",**array+2); *array[2]: 8
printf("*(*(array+1)+2): %d\n",*(*(array+1)+2));
*array+2: effff80c
printf("*(array+1)+2: %x\n",*(array+1)+2);**array+2: 2
printf("*array[3]: %x\n",*array[3]);
*(*(array+1)+2): 6
}
*(array+1)+2:
effff81c
*array[3]: 0
Character Pointers and Functions

When an array name is passed to a function, what is


passed is the location of the first element.

Within the called function, this array name


is a local pointer variable!
That means, as a formal parameter in a function
definition, char s[] and char *s are equivalent.
// return length of string s
int strlen(char s[])
{
int n;

for (n = 0; *s != '\0'; s++)


n++;
• The following calls will work: return n;
strlen(a); // char a[10]; }
strlen(p); // char *p;
strlen("hello world"); // string constant !!
A Test Program
#include <stdio.h> a
/* Return length of string s */
int strlen(char s[]) •'h'
{ •'e'
int n; •'l'
for (n = 0; *s != '\0'; s++) •'l'
n++; •'o'
return n; •'\0'
} p

main()
{ int i1, i2, i3;
char a[] = "hello";
char *p = a;

i1 = strlen(a);
i2 = strlen(p);
i3 = strlen("hello");
}
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)

pp is a “pointer to” a
#include <stdio.h>
“pointer to an int”
int main(void)
{
int i = 16;
int *p = &i; i
16
int **pp; 0x2320

pp = &p; p
0x2320
printf("%i\n", **pp);
0x2324
return 0; pp
} 0x2324
0x2328
int main(void) i j k
{
int i = 10, j = 7, k;
int *p = &i;
int *q = &j; p q
int *pp = &p;
pp
**pp += 1;

*pp = &k;

**pp = *q;

i = *q***pp;

i = *q/**pp; /* headache?
*/;

return 0;
}
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 month\0January\0February\0
March\0April\0May\0June\0July\0August\0
September\0October\0November\0December\0
Arrays of Pointers
• The pointers are initialized like so

Illegal month\0January\0February\0
March\0April\0May\0June\0July\0August\0
September\0October\0November\0December\0
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 ");}
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 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;}
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 = %d\n”, argc) ;
for (i=0; i<argc; ++i)
printf (“argv[%d] = %s\n”,
i,argv[i]) ;
return 0; C:\> p1 how many
} argc = 3
argv[0] = p1
argv[1] = how
argv[2] = many

You might also like