Programming Pointers. Variables in Memory 10001003100410051012 x i c The compiler determines where...

51
Programming Pointers
  • date post

    22-Dec-2015
  • Category

    Documents

  • view

    222
  • download

    0

Transcript of Programming Pointers. Variables in Memory 10001003100410051012 x i c The compiler determines where...

Programming

Pointers

Variables in Memory

1000 1003 1004 1005 1012

xi c

The compiler determines where variables are placed in memory

This placement cannot be changed by the programmer

int n;char c;double x;

Address of Operator

The operator & gives the address of a variable in memory &i is 1000 &c is 1004 &x is 1005

1000 1003 1004 1005 1012

i c xi c

Address of Operator

Can only be applied to variables in memory Cannot be applied to expressions and

constants &3 &(x + 1) &(a == b)

Address Variables (Take 1)

An address is just a number let’s use an integer to hold it

int address_n = &n, address_c = &c, address_x = &x;

Problem?

Value Given Address

The * operator access the content of a variable given its address

*address_n gives the value of the variable n

How can we tell how many bytes we need to read given an address?

We need both the variable’s address and its size

Address Variables (Take 2)

Pointers are variables that hold the address of other variables. starting address type (size)

1000 1003 1004

i ci c ip1000 1004

cp

A pointer is declared by adding a * before the variable name.

double *dp; int *ip, n; char* cp1, *cp2;

type* variable_name;

Declaring a Pointer Variable

pointer to double

pointer to int “regular” int

pointer to char another pointer to char

Referencing

The operator & gives the address of a variable

ptr = &c;Assigns the address of c to the pointer ptr

We say that ptr points to c

Dereferencing

The operator * is the dereferencing operator

Access the variable the pointer points to

int n = 1, m = 2;int* ip;

ip = &n;m = *ip;*ip = 0;

ip is a pointer to int

ip now points to xip now points to n

m is now 1

n is now 0

Is This OK?

int ival = 1024, ival2 = 2048;

int* pi1 = &ival, *pi2 = &ival2;

ival = pi2;

int int*

warning C4047: '=' : 'int' differs in levels of indirection from 'int'*

Is This OK?

int ival = 1024, ival2 = 2048;

int* pi1 = &ival, *pi2 = &ival2;

pi2 = *pi1;

int* int

warning C4047: '=' : 'int *' differs in levels of indirection from 'int'

Is This OK?

int ival = 1024, ival2 = 2048;

int* pi1 = &ival, *pi2 = &ival2;

ival = *pi1;

int int ✓

Is This OK?

int ival = 1024, ival2 = 2048;

int* pi1 = &ival, *pi2 = &ival2;

pi1 = ival;

int* int

warning C4047: '=' : 'int *' differs in levels of indirection from 'int'

NULL

Special “address” indicating “nowhere” int* ip = NULL;

ip does not point to any variable We can test

if (ip != NULL) { *ip = …;

}

Function Arguments - Reminder

Changes to the local variable do not modify the value in the caller

Call “by value”

void increment_counter(int counter){ counter++;}

int main(void){ int count; ... increment_counter(count);}

We can access the variable pointed to by the local variable

Call “by reference”

Pointers as Function Arguments

void increment_counter(int* counter){ (*counter)++;}

int main(void){ int count; ... increment_counter(&count);}

main

incerement_counter(&count)

Caller Callee

main

incerement_counter(count)

count

by value

increment_counter(int counter)

by reference

increment_counter(int* counter)

copy of count

counter

Pointers as Function Arguments

scanf Revisited

We can now understand the & in scanf("%d", &a);

The argument list in scanf is simply passed by address, so scanf can change its content

Exercise

Implement the function: void split(double d, int* i_part, double* f_part);

The function accepts a double parameter and assigns its integer and fraction parts to the two variable pointed to by i_part and f_part respectively.

Write a program that accepts a number from the user and prints out its integer and fraction parts.

Solutionvoid split(double d, int* i_part, double* f_part){ *i_part = (int)d; *f_part = d – (*i_part);}

int main(void){ double num, fraction; int integer;

printf("Please enter a real number: "); scanf("%lf", &num);

split(num, &integer, &fraction); printf("The integer part is %d\n", integer); printf("The remaining fraction is %g\n", fraction);

return 0;}

Example - Swap

void swap(int* x, int* y){ int temp = *x; *x = *y; *y = temp;

}

Call swap: swap(&x, &y);

Const Pointers

A pointer can be declared constantconst int* cip;

The pointer can be changed, but the object it points to can not. cip = &i; ✓ cip = &j; ✓ *cip = 5; ✗

Pointers as Return Values

A function may return the address of a variable

The variable must not be a local variable

char* strchr(const char* str, char c){ while (*str != '\0') { if (*str == c) return str; ++str; } return NULL;}

Address, Pointers and Arrays

int a[10];Defines a block of 10 consecutive objects named a[0],a[1],…,a[9].

The name of the array is a synonym for the location of the first element. a is &a[0]

The name of the array is not a variable, hence its value cannot be modified.

a[0] a[1] a[9]

a:

Address, Pointers and Arrays

a[0] a[1] a[9]

a:

int a[10];int *pa;

pa:

int a[10];int* pa;

pa = &a[0];

Array Names are Not Pointers

Pointers are variables (can be modified) legal:

pa = a pa++

Array name is not a variable (cannot be modified) illegal:

a = pa a++

Pointers Vs. Arrays - Example

int arr[3] = {1, 2, 3};int* ptr;const int* cptr;

arr = ptr;ptr = arr;*ptr = 3;cptr = arr;*cptr = 5;ptr = cptr;*arr = 6;

Pointer Arithmetic

If pa points to an element in the array, then pa+1 points to the next element

pa+i points I elements after pa

a[0] a[1] a[9]

a:

pa:

pa+1:

pa+2:

Pointer Arithmetic

if pa points to a[0]*(pa + 1) is the content of a[1]

*(pa + i) is equivalent to a[i]

More Pointer Arithmetic

Pointers can be incremented and decremented p++ advance p one place in the array p += I advances p i places in the array

Example:if str points to the first character of a string then str + strlen(str) -1 points to the last character

Pointers and Increment Operators

Walk down an array

Pointer notation ++(*p) - increment thing pointed to (*p)++ - increment thing pointed to *(p++) - fetch value, then increment pointer *(++p) - increment pointer, then fetch value

int ar[ARLEN], *ip;ip = ar;while(ip < &ar[ARLEN]) *(ip++) = 0;

Reverseint main(void){ char str[STR_SIZE + 1]; char* ptr = NULL;

printf("Enter a string:\n"); getline(str, STR_SIZE);

for (ptr = str + strlen(str) - 1; ptr >= str; --ptr) { putchar(*ptr); } putchar('\n');

return 0;}

\0str:

ptr:

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’ ‘s’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’ ‘s’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’ ‘s’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’ ‘s’

dest

...

...

my_strcpy

void my_strcpy(char* dest, const char* src){ while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0';}

‘y’ ‘e’ ‘s’ \‘0’

src

‘y’ ‘e’ ‘s’ \‘0’

dest

...

...

Using my_strcpy

int main(void){ char str[STR_LEN + 1], temp[SR_LEN + 1];

... my_strcpy(temp, str); ...}

Common Error

Return of a local array

char* foo(const char* str){ char temp[BIG_ENOUGH];

strcpy(temp, str);

/* manipulate temp */ . . .

return temp; }

Exercise

Write a function with the prototype:void replace_char(char* str,

char c1, char c2);

It replaces each appearance of c1 by c2 in the string str. Do not use the [] operator!

Demonstrate your function with a program that uses it

Solution

void replace_char(char* str, char c1, char c2){ if (str == NULL) return;

while (*str != '\0') { if (*str == c1) *str = c2;

++str; }}