UNIT 6: POINTERSCS103L FALL 2019
TEXT
POINTER MOTIVATION
▸ Scenario:
▸ Collaborating on a writing project. Lots of images. Document ends up being quite large.
▸ How to share the document?
▸ E-mail around a copy of the Word document as an attachment
▸ Upload to Google docs and e-mail URL
TEXT
POINTER MOTIVATION
▸ These two methods are quite different!
▸ Google Doc: much less info to send: URL = ~hundred characters, doc = 100MB
▸ Google Doc: everyone has access to the same document for collaboration
▸ E-mail: each person has own copy, can edit freely and privately
▸ We will see this analogy holds well for pointers.
▸ URL -> pointer to document
TEXT
POINTER PREVIEW
▸ Pointers in C++ will let us do the following (details later, of course!)
▸ Change the value of a variable declared in one function with a 2nd function
▸ Pass large data structures around a program without making copies
▸ Making copies is not free!
▸ Utilize dynamic memory
▸ allocate and de-allocate memory as program runs
▸ Interact with hardware based I/O (embedded systems)
TEXT
ANOTHER POINTER ANALOGY
▸ Safe Deposit Boxes
30
PointerstoPointersAnalogy• Wecanactuallyhavemultiplelevelsof
indirection(de-referencing)• UsingC/C++pointerterminology:
– *9=goldinbox7 (9=>7)– **16=goldinbox3 (16=>5=>3)– ***0=goldinbox3 (0=>8=>5=>3)
0 1 2 3 4 5
12 13 14 15 16 17
6 7 8 9 10 118 15 3
711
1 5 3
35
TEXT
POINTER BASICS
▸ So what is a pointer?
▸ Remember:
▸ In C++ variables live in memory
▸ Each memory location has an address
▸ Address is just another way of referring to the location *where* a variable is stored
TEXT
POINTER BASICS
▸ Pointers are VARIABLES
▸ Just like any other variable, has a value and is stored at a location
▸ Pointers simply store the address of *another* variable
▸ Value of a pointer is the memory location of another variable
▸ Other variable can be any C++ type: int, double, char… or even another pointer
▸ Also called references, because they can be used to “refer” to other variables
TEXT
REFERENCES
▸ The idea of a reference is very common
▸ URL is a reference to a website
▸ Phone number is a reference to your phone or VM box
▸ Excel sheets: =A1 is a reference in one cell that brings in data from another cell
TEXT
DECLARING POINTERS
▸ Just like other variable types, we can declare pointer variables
▸ This gives us a place to *store* the address of something
▸ Pointers are typed too! Need to know what type the point to.
▸ int* ptr; (create a pointer to an int)
▸ char* chr_ptr; (create a pointer to a char)
▸ double* d; (create a pointer to a double)
TEXT
POINTER SIZE
▸ Like all variables, pointers have a size, or number of bits
▸ 32-bits on some platforms
▸ 64-bits on more modern platforms: Intel, AMD, ARM
TEXT
POINTER OPERATORS
▸ In C++ we have two operators that let us work with pointers:
▸ & operator
▸ * operator
TEXT
& OPERATOR
▸ & operator is the “address-of” operator
▸ Returns the address of the variable it touches: &<variable name>
▸ &x, &y, &start_val, &index, &score
▸ Returns a pointer!
▸ An address is a pointer.
▸ Now we can fill our pointer variables:
▸ int x = 10;
▸ int* x_ptr = &x
TEXT
* OPERATOR
▸ * operator: pointer dereferencing operator
▸ Gives us the data (resolves the reference, aka de-references) at an address (so from a pointer)
▸ int x = 10;
▸ int* ptr = &x;
▸ cout << *ptr << endl;
▸ What does this print?
TEXT
& AND * OPERATORS
▸ & and * are inverses of each other:
▸ &value => address
▸ *address => value
▸ *(&value) => value
TEXT
& AND * HINTS
▸ Use & when you need to turn a variable into a pointer to that variable
▸ Use * when you need to get the value that lives at the address contained in a pointer
▸ Remember: a pointer is a variable, just a special kind that holds the address of another variable
TEXT
POINTERS AND ARRAYS
▸ Remember the mantra:
▸ int dat[10];
▸ What does the variable name ‘dat’ by itself resolve to?
▸ The starting address of dat! a.k.a a pointer to dat[0]
▸ or sometimes we say “the starting address of the dat array”
▸ Both show us ‘dat’ is just a pointer to the array
TEXT
LOOKING AT SOME POINTERS
▸ &x = ??
▸ &y = ??
▸ &z = ??
▸ &dat[1] = ??
▸ dat = ??
9
Pointers• ‘&’operatoryieldsaddressofavariableinC
(Tip:Read‘&foo’as‘addressoffoo’)– int x=30;chary=‘a’;
floatz=5.375;int dat[2]={107,43};
– &x =>??,– &y =>??,– &z =>??,– &dat[1] =??;– dat =>??
Memory
20bc420bc820bcc20bd020bd4
20bc0 0030‘a’5.37510743
…
0000
20bd820bdc
0020be0…
x
dat[1]
…
yz
dat[0]
int x = 30;
char y=‘a’;
float z= 5.375
int dat[2] = {107, 43};
TEXT
LOOKING AT SOME POINTERS
▸ &x = 0x20bc4
▸ &y = 0x20bc8
▸ &z = 0x20bcc
▸ &dat[1] = 0x20bd4
▸ dat = 0x20bd0
9
Pointers• ‘&’operatoryieldsaddressofavariableinC
(Tip:Read‘&foo’as‘addressoffoo’)– int x=30;chary=‘a’;
floatz=5.375;int dat[2]={107,43};
– &x =>??,– &y =>??,– &z =>??,– &dat[1] =??;– dat =>??
Memory
20bc420bc820bcc20bd020bd4
20bc0 0030‘a’5.37510743
…
0000
20bd820bdc
0020be0…
x
dat[1]
…
yz
dat[0]
int x = 30;
char y=‘a’;
float z= 5.375
int dat[2] = {107, 43};
TEXT
DECLARING POINTERS
▸ Just like we declare a variable to hold and int, or double we declare a pointer to hold the address of some other variable
▸ Use the * when declaring to modify the type
11
Pointers• Justaswedeclarevariablestostoreint’s anddouble’s,
wecandeclareapointervariable tostorethe“address-of”(or“pointer-to”)anothervariable– Requires4-bytesofstorageina32-bitsystemor
8-bytesina64-bitsystems– Usea‘*’afterthetypetoindicatethisapointervariable
tothattypeofdata• Whydidpeoplechoose'*'todeclareapointervariable?• Becauseyou'dhavetoputa'*'infrontofthevariableto
getanactualdataitem(i.e.togettheint thatanint pointerpointsto,puta'*'infrontofthepointervariable.
• Declarevariables:– int x = 30; char y='a';
float z = 5.375;int dat[2] = {107,43};
– int *ptr1; ptr1 = &x; // ptr1 = 0x20bc4ptr1 = &dat[0]; // Change ptr1 = 0x20bd0 //(i.e.you can change what a pointer points to)
– float *ptr2 = &z; // ptr2 = 0x20bcc
Memory
20bc420bc820bcc20bd020bd4
20bc0 0030‘a’5.37510743
…
20bd820bdc
0020be0…
x
dat[1]
yz
dat[0]
ptr1ptr2
int x = 30; char y=‘a’; float z= 5.375 int dat[2] = {107, 43};
int *ptr1; ptr1 = &x; //ptr1 = 0x20bc4 ptr1 = &dat[0]; // ptr1 is now 0x20bd0 //note: this shows you can change the value of a pointer float* ptr2 = &z;
0x20bc40x20bd00x20bcc
TEXT
DE-REFERENCING
▸ Once a pointer points somewhere, we need a way to get the *value* at the destination
▸ Use the * operator (dereference)
▸ *var = “value pointed to by var” or “value at address given by var”
13
De-referencing/Indirection• Onceapointerhasbeenwrittenwithanaddressofsome
otherobject,wecanuseittoaccessthatobject(i.e.dereferencethepointer)usingthe‘*’ operator
• Read‘*foo’as…– ‘valuepointedtobyfoo’
– ‘valueattheaddressgivenbyfoo’(not‘valueoffoo’or‘valueofaddressoffoo’)
• UsingURLanalogy,usingthe*operatoronapointerislike“clickingonaURL”(followthelink)
• Examples:– ptr1=dat;
int a=*ptr1+5;
– (*ptr1)++;//*ptr =*ptr +1;
– *ptr2 =*ptr1 - *ptr2;
Memory
20bc420bc820bcc20bd020bd4
20bc0 0030‘a’5.37510743
…
20bd020bcc
20bd820bdc
0020be0…
x
dat[1]
yz
dat[0]
ptr1ptr2a
ptr1 = dat; int a = *ptr1 + 5; (*ptr1)++; // *ptr1 = *ptr1 + 1; *ptr2 = *ptr1 - *ptr2;
a = 112dat[0] = 108
z = 108 - 5.375 = 102.625
TEXT
SYNTAX CHECK
15
CuttingthroughtheSyntax• ‘*’inatypedeclaration=declare/allocateapointer• ‘*’inanexpression/assignment=dereference
Declaringapointer De-referencingapointer
char *p*p+1int *ptr*ptr =5*ptr++char *p1[10];
YesYes
YesYesYes
Yes
Helpful tip to understand syntax: We declare an int pointer as:• int *p because when we dereference it as *p we get an int• char *x is a declaration of a pointer and thus *x in code yields a char
TEXT
POINTER CHECK POINT
int x,y; int *p = &x; int *q = &y; x = 35; y = 46; p = q; *p = 78; cout << x << “ “ << y << endl; cout << *p << “ “ << *q << endl;
TEXT
POINTER/ARRAY REVIEW
▸ Review:
▸ sizeof(int)?
▸ sizeof(double)?
▸ What does the name of an array evaluate to?
▸ If we declare int dat[4] and dat = 0x200, where is dat[1]? dat[2]?
TEXT
POINTER ARITHMETIC
▸ Pointers are *just* variables that happen to store the address of another variable, an address is just a number
▸ So we can imagine doing math with the numbers
▸ int dat[2]; int* ptr = dat;
▸ ptr++;
▸ If dat=0x200, which makes more sense:
▸ ptr is now 0x201
▸ ptr is now 0x204
TEXT
POINTER ARITHMETIC
▸ Pointer arithmetic shows duality between pointers and arrays
▸ Adding/subtracting to a pointer adjusts it by the size of the data type
▸ int* ptr = dat; ptr++ //increase ptr by 4
▸ char* ptr = name; ptr++ //increase ptr by 1
▸ double* ptr = data; ptr++ //increase ptr by 8
TEXT
POINTER ARITHMETIC
▸ Why do this strange (but helpful) math?
▸ What does the name of an array resolve to?
▸ The address of the first element = pointer to the first element
▸ C/C++ make no distinction between an array and a pointer
▸ Pointer arithmetic lets you iterate over or skip around an array with math:
▸ int dat[10]; int* ptr = dat;
▸ cout << dat[i];
▸ cout << *(ptr+i);
TEXT
POINTER ARITHMETIC EXAMPLE
19
PointerArithmetic• Pointersarevariablesstoringaddressesand
addressesarejustnumbers• Wecanperformadditionorsubtractiononthose
pointervariables(i.e.addresses)justlikeanyothervariable
• Thenumberadded/subtractedisimplicitlymultipliedbythesizeoftheobjectsothepointerwillpointtoavaliddataitem– int *ptr =dat;ptr =ptr +1;– //addressinptr wasincrementedby4
• Examples:– ptr1=dat;– x=x+*ptr1;//x=137– ptr1++;//ptr1nowpointsatdat[1]– x=x+*ptr1++;//x=dat[1]=137+43then
//inc.ptr1to0x20bd8– ptr1=ptr1-2;//ptr1nowpointsbackatdat[0]
Memory
20bc420bc820bcc20bd020bd4
20bc0 0030‘a’5.37510743
…
20bd020bcc
20bd820bdc
0020be0…
x
dat[1]
yz
dat[0]
ptr1ptr2
ptr1 = dat; //point ptr1 at dat[0]
x = x + *ptr1; //x = 137
ptr1++; //ptr1 now points to dat[1]
x = x + *ptr1; //x = 137 + 43
ptr1 -= 1; //ptr1 now points back to dat[0]
TEXT
POINTERS AND ARRAY INDEXING
▸ C/C++ make no distinction between pointer arithmetic and array indexing
▸ They are equivalent!
▸ Array syntax: data[i]
▸ get the item at the i-th index from the start of the data array)
▸ Pointer syntax *(data + i)
▸ Add i*sizeof() to the data pointer and dereference to get value
▸ There are exactly the same operation!
TEXT
MORE POINTER/ARRAY EXAMPLES
int data[10]; //data lands at memory address 520
*(data+4) = 50; //data[4] = 50;
int* ptr = data; //now ptr can be used to access data array
ptr[1] = ptr[2] + ptr[3]; //same as data[1] = data[2]+data[3]
20
PointerArithmeticandArrayIndexing• Arrayindexingandpointerarithmeticareverymuchrelated
• Arraysyntax:data[i]– Saysgetthei-th valuefromthestartofthedataarray
• Pointersyntax:*(data+i)– Saysthesamethingasdata[i]
• Wecanusepointersandarraynamesinterchangeably:– int data[10];//data=520;
– *(data+4)=50;//data[4]=50;
– int*ptr =data;//ptr nowpointsat520too
– ptr[1]=ptr[2]+ptr[3];//sameasdata[1]=data[2]+data[3]
Memory
520
09 08 07 06 50 04524 528 532 536 540
…
data = 520
int data[10]
520ptr
TEXT
ANOTHER POINTER/ARRAY EXAMPLE21
Arrays&Pointers• Haveauniquerelationship• Arraynameevaluatestostart
addressofarray– Thus,thenameofaninteger
arrayhastype:int*– Thenameofcharacterarray/
textstringhastype:char*
• Arrayindexingissameaspointerarithmetic
int main(int argc, char *argv[]){int data[10] = {9,8,7,6,5,4,3,2,1,0};
int* ptr, *another; // * needed for each// ptr var. you // declare
ptr = data; // ptr = start address // of data
another = data; // another = start addr.
for(int i=0; i < 10; i++){data[i] = 99;ptr[i] = 99; // same as line above*another = 99; // same as line aboveanother++;
}
int x = data[5];x = *(ptr+5); // same as line abovereturn 0;
}
TEXT
SO WHY USE POINTERS?
▸ Reason #1 (from slide 4)
▸ “Change the value of a variable declared in one function with a 2nd function”
▸ Known as pass-by-reference
▸ We got a preview with passing arrays (which are just pointers!)
TEXT
PASS BY REFERENCE
▸ We know this doesn’t work
▸ Why?
▸ Pass-by-value
▸ A *copy* of the actual parameter is passed into the formal parameter
23
Code for all functions
PassbyValue• Noticethatactualargumentsaredifferent
memorylocations/variablesthantheformalarguments
• Whenargumentsarepassedacopy oftheactualargumentvalue(e.g.3)isplacedintheformalparameter(x)
• Thevalueofycannotbechangedbyanyotherfunction(rememberitislocal)
Data for main (a, y=3) and return link
Data for decrement_it(y=3 then 2) and return link
System stack area0xffff ffff
0x0000000
System Memory
(RAM)
Address Code for all functions
void decrement_it(int);
int main(){int a, y = 3;decrement_it(y);cout << “y = “ << y << endl;
}
void decrement_it(int y){
y--;}
Data for main (a, y=3) and return link
23
Code for all functions
PassbyValue• Noticethatactualargumentsaredifferent
memorylocations/variablesthantheformalarguments
• Whenargumentsarepassedacopy oftheactualargumentvalue(e.g.3)isplacedintheformalparameter(x)
• Thevalueofycannotbechangedbyanyotherfunction(rememberitislocal)
Data for main (a, y=3) and return link
Data for decrement_it(y=3 then 2) and return link
System stack area0xffff ffff
0x0000000
System Memory
(RAM)
Address Code for all functions
void decrement_it(int);
int main(){int a, y = 3;decrement_it(y);cout << “y = “ << y << endl;
}
void decrement_it(int y){
y--;}
Data for main (a, y=3) and return link
TEXT
PASS-BY-POINTER (AKA PASS-BY-REFERENCE)
▸ Rewrite to use pointers. Now it works.
▸ Pointer value (memory address) is still passed-by-value
▸ But we can dereference the memory address to manipulate the value!
▸ The *value* of y in main() is changed and persists after decrement_it() runs
24
Code for all functions
PassbyReference• Pointervalue(i.e.theaddress)isstillpassed-by-
value(i.e.acopyismade)• However,thevalueofthepointerisareference
toy(i.e.y’s address)anditisreallythevalueofythatdoit()operateson
• Thuswesaywearepassing-by-reference• ThevalueofyisCHANGEDbydoit()andthat
changeisvisiblewhenwereturn.
Data for main (a=??, y=3, ptr=0x20bd4) and return link
System stack area0xffff ffff
0x0000000
System Memory
(RAM)
Address Code for all functions
int main(){int a, y = 3;// assume y @ 0x20bd4 // assume ptra = y;decrement_it(&y);cout << “a=“ << a;cout << “y=“ << y << endl;return 0;
}
// Remember * in a type/// declaration means “pointer” // variablevoid decrement_it(int* x){
*x = *x - 1;}
Data for main (a=3, y=3) and return link
Resulting Output:a=3, y=2
Data for doit(x=0x20bd4) and return link
Data for main (a=3, y=2) and return link
24
Code for all functions
PassbyReference• Pointervalue(i.e.theaddress)isstillpassed-by-
value(i.e.acopyismade)• However,thevalueofthepointerisareference
toy(i.e.y’s address)anditisreallythevalueofythatdoit()operateson
• Thuswesaywearepassing-by-reference• ThevalueofyisCHANGEDbydoit()andthat
changeisvisiblewhenwereturn.
Data for main (a=??, y=3, ptr=0x20bd4) and return link
System stack area0xffff ffff
0x0000000
System Memory
(RAM)
Address Code for all functions
int main(){int a, y = 3;// assume y @ 0x20bd4 // assume ptra = y;decrement_it(&y);cout << “a=“ << a;cout << “y=“ << y << endl;return 0;
}
// Remember * in a type/// declaration means “pointer” // variablevoid decrement_it(int* x){
*x = *x - 1;}
Data for main (a=3, y=3) and return link
Resulting Output:a=3, y=2
Data for doit(x=0x20bd4) and return link
Data for main (a=3, y=2) and return link
TEXT
HERE COMES SWAP AGAIN!
▸ Task: write function to swap the value of two variables.
▸ We know pass-by-value won’t work.
▸ Swap would be performed on variables *local* to the function
▸ With pointers, we can implement swap
▸ Memory address are passed in and dereferenced to perform swap
25
SwapTwoVariables• Classicexampleofissueswithlocal
variables:– Writeafunctiontoswaptwovariables
• Pass-by-valuedoesn’twork– Copyismadeofx,y frommainand
passedtox,y ofswapit…Swapisperformedonthecopies
• Pass-by-reference(pointers)doeswork– Addressesoftheactualx,y variablesin
mainarepassed– Usethoseaddresstochangethose
physicalmemorylocations
int main(){int x=5,y=7;swapit(x,y);cout << "x=" << x << " y=";cout << y << endl;
}
void swapit(int x, int y){ int temp;
temp = x;x = y;y = temp;
}
int main(){ int x=5,y=7;swapit(&x,&y);cout << “x=“ << x << “y=“;cout << y << endl;
}
void swapit(int *x, int *y){ int temp;
temp = *x;*x = *y;*y = temp;
}
program output: x=5,y=7
program output: x=7,y=5
TEXT
PASSING ARRAYS AS ARGUMENTS
▸ We’ve seen this in “arrays” lecture, now we understand even better
▸ Remember C/C++ doesn’t keep track of the size for us, so *most* functions that take arrays will also take a size parameter
26
PassingArraysasArguments• Infunctiondeclaration/prototypefor
theformal parameteruse– “type[]”or“type*”toindicateanarray
isbeingpassed• Whencallingthefunction,simply
providethenameofthearrayastheactual argument– InC/C++usinganarraynamewithout
anyindexevaluatestothestartingaddressofthearray
• CdoesNOTimplicitlykeeptrackofthesizeofthearray– Thuseitherneedtohavethefunction
onlyacceptarraysofacertainsize– Orneedtopassthesize(length)ofthe
arrayasanotherargument
void add_1_to_array_of_10(int []);void add_1_to_array(int *, int);int main(int argc, char *argv[]){int data[10] = {9,8,7,6,5,4,3,2,1,0};add_1_to_array_of_10(data);cout << “data[0]” << data[0] << endl;add_1_to_array(data,10);cout << “data[9]” << data[9] << endl;return 0;
}
void add_1_to_array_of_10(int my_array[]){int i=0;for(i=0; i < 10; i++){my_array[i]++;
}}
void add_1_to_array(int *my_array, int size){int i=0;for(i=0; i < size; i++){my_array[i]++;
}}Memory
520
09 08 07 06 05 04524 528 532 536 540
…
520
520
520
520
TEXT
ARGUMENT PASSING EXAMPLE
▸ Now we can write helpful functions that do useful things on arrays
27
Memory (RAM)
main: (len = 0
data[0] = ?
data[1] = ?
data[2] = ?
…)
ArgumentPassingExample
…
Code
Globals
0
…
Heap
fffffffc
Address#include <iostream>using namespace std;
int main(){int len=0;int data[100];
len = fill_data(data, 100);
for(int i=0; i < len; i++)cout << data[i] << “ “;
cout << endl;return 0;
}
// fills in integer array w/ int’s// from user until -1 is enteredint fill_data(int *array, int max){
int val = 0;int i = 0;while(i < max){cin >> val;if (val != -1)array[i++] = val;
else break;
}return i;
}
…
fill_data(array=0xbf008,
max = 100
val=0, i = 0)
0xbf0040xbf008
0xbf00c
Memory (RAM)
main: (len = 2
data[0] = 4
data[1] = 3
data[2] = ?
…)
…
Code
Globals
0
…
Heap
fffffffc
Address
…
fill_data(array=0xbf008,
mas = 100
val = -1, i = 2)
0xbf0040xbf008
0xbf00c
TEXT
IN CLASS EXCERCISES
▸ Swap
▸ Roll2
▸ Product
TEXT
POINTERS TO POINTERS
▸ Say what?
▸ As if pointers are not confusing enough!
▸ Extend our safe deposit box analogy
TEXT
POINTERS TO POINTERS ANALOGY
▸ A box might contain gold
▸ Or it contains a box-id (and presumably the key)
▸ You can follow the chain of box-ids until you find the gold
▸ No limit to the # of indirections
▸ *9 = gold in box 7 (9 -> 7)
▸ **16 = gold in box 3 (16 -> 5 -> 3)
▸ ***0 = gold in box 3 (0 -> 8 -> 5 -> 3)
30
PointerstoPointersAnalogy• Wecanactuallyhavemultiplelevelsof
indirection(de-referencing)• UsingC/C++pointerterminology:
– *9=goldinbox7 (9=>7)– **16=goldinbox3 (16=>5=>3)– ***0=goldinbox3 (0=>8=>5=>3)
0 1 2 3 4 5
12 13 14 15 16 17
6 7 8 9 10 118 15 3
711
1 5 3
35
TEXT
POINTERS TO POINTERS
▸ In C/C++ we can do the same thing.
▸ Remember, pointers are variables.
▸ They just happen to hold the memory address of another variable.
▸ Now they just happen to hold the memory address of another variable that also happens to hold the memory address of…(like inception)
TEXT
LEVELS OF INDIRECTION
▸ Since we can have as many levels of indirection as we want, we need to tell compiler how many there are when declaring the pointers:
int *p; //pointer to an int, one hop away
double **q; //pointer to a double, two hops away
TEXT
POINTERS TO POINTERS
▸ So now we can create pointers to pointers, what does that look like?
int k, x[3] = {5,7,9};
int *ptr1, **ptr2;
ptr1 = x;
ptr2 = &ptr1;
k = *ptr1;
k = (**ptr2) + 1;
k = *(*ptr2 + 1);
Declaration Expression Yields
int *ptr1 *ptr int
int **ptr2 **ptr2 int
*ptr2 int*
TEXT
POINTERS TO POINTERS
▸ Follow the chain…
33
PointerstoPointersto…
• Pointerscanpointtootherpointers– Essentiallyachainof“links”
• Example– int k,x[3]={5,7,9};– int *myptr,**ourptr;– myptr =x;– ourptr =&myptr;– k=*myptr;//k=5– k=(**ourptr)+1;//k=6– k=*(*ourptr +1);//k=7
Memory
20bc420bc820bcc20bd020bd4
20bc0 00579
20bc420bd0
…
0000
20bd820bdc
0020be0…
X[0]
ourptr
X[1]X[2]myptr
kint k, x[3] = {5,7,9};
int *ptr1, **ptr2;
ptr1 = x;
ptr2 = &ptr1;
k = *ptr1; //k = 5
k = (**ptr2) + 1; //k = 6
k = *(*ptr2 + 1); //k = 7
TEXT
POINTERS TO POINTER REVIEW
▸ Consider the declarations: int k, x[3] = {5,7,9};
int *ptr1, **ptr2;
Expression Typex[0] int
x int*ptr1 int**ptr1 int*ptr2 int*
ptr1+1 int*ptr2 int**
TEXT
C-STRING CONSTANTS
▸ Review: text in “double quotes” is a string constant
▸ The end up being an array of NULL terminated char’s (c-string)
▸ Assigned memory address
▸ If you check, the type is const char*
▸ You cannot/should not *change* these strings (hence the const)
37
C-StringConstants• C-Stringconstantsarethethings
wetypein"…" andarestoredsomewhereinmemory(chosenbythecompiler)
• WhenyoupassaC-stringconstanttoafunctionitpassesthestartaddressandit'stypeisknownasaconst char*– char*becauseyouarepassingthe
address– const becauseyoucannot/shouldnot
changethisarray'scontents
int main(int argc, char *argv[]){// These are examples of C-String constantscout << "Hello" << endl;cout << "Bye!" << endl;...
}
B y e ! \0
240 244H e l l \0o
300 305
#include <cstring>//cstring library includes//void strcpy (char * dest, const char* src);int main(int argc, char *argv[]){char name[40];strcpy(name, "Tommy");
}
name = 240 279T o m m \0y
300 305
300
300
240
TEXT
ARRAYS OF POINTERS AND C-STRINGS
▸ Sometimes need to store several arrays
▸ The arrays are related, like names
▸ C-strings are arrays of char variables
▸ Is this a good way to do it?
38
Arraysofpointers
• Weoftenwanttohaveseveralarraystostoredata– Storeseveraltextstrings
• Thosearraysmayberelated(i.e.allnamesofstudentsinaclass)
int main(int argc, char *argv[]){int i;char str1[] = “Bill”;char str2[] = “Suzy”;char str3[] = “Pedro”;char str4[] = “Ann”;
// I would like to print out each namecout << str1 << endl;cout << str2 << endl;...
}
Painful
B i l l \0str1=240 244
S u z y \0
P e d r \0o
A n n \0
str2=288 292
str3=300 305
str4=196 199
38
Arraysofpointers
• Weoftenwanttohaveseveralarraystostoredata– Storeseveraltextstrings
• Thosearraysmayberelated(i.e.allnamesofstudentsinaclass)
int main(int argc, char *argv[]){int i;char str1[] = “Bill”;char str2[] = “Suzy”;char str3[] = “Pedro”;char str4[] = “Ann”;
// I would like to print out each namecout << str1 << endl;cout << str2 << endl;...
}
Painful
B i l l \0str1=240 244
S u z y \0
P e d r \0o
A n n \0
str2=288 292
str3=300 305
str4=196 199
TEXT
ARRAYS OF POINTERS TO C-STRINGS
▸ Is this better?
▸ Somewhat?
▸ What does names resolve to?
▸ The address of the first char*
▸ names has what type? char**
▸ What type does names[0] have?
▸ char*
39
Arraysofpointers
• Weoftenwanttohaveseveralarraystostoredata– Storeseveraltextstrings
• Thosearraysmayberelated(i.e.allnamesofstudentsinaclass)
• Whattypeis'names'?– Theaddressofthe0-thchar*
inthearray– Theaddressofachar*is
reallyjustachar**
int main(int argc, char *argv[]){int i;char str1[] = “Bill”;char str2[] = “Suzy”;char str3[] = “Pedro”;char str4[] = “Ann”;char *names[4];
names[0] = str1; ...; names[3] = str4;for(i=0; i < 4; i++){cout << names[i] << endl;
} ...
}Still painful
B i l l \0240 244
S u z y \0
P e d r \0o
A n n \0
288 292
300 305
196 199
names = 520524528
532
names[0]names[1]names[2]
names[3]
240288300196
TEXT
ARRAYS OF POINTERS
▸ Remember a pointer is just another variable, so we can have arrays of pointers (just like we could have an array of ints)
40
Arraysofpointers
• Wecanhavearraysofpointersjustlikewehavearraysofotherdatatypes
• Usuallyeachvalueofthearrayisapointertoacollectionof“related”data– Couldbetoanotherarray
char *names[4] ={“Bill”,“Suzy”,“Pedro”,“Ann”};
int main(int argc, char *argv[]){int i;
for(i=0; i < 4; i++){cout << names[i] << endl;
}return 0;
}
B i l l \0240 244
S u z y \0
P e d r \0o
A n n \0
288 292
300 305
196 199
names = 520 240524528
532
288300196
names[0]names[1]names[2]
names[3]
Painless?!?
TEXT
NOW WE CAN UNDERSTAND COMMAND LINE ARGUMENTS
▸ When we run a command, the shell gives our program some information:
▸ int argc -> #of command line arguments
▸ char* argv[] -> array argc# of pointers to C-strings
▸ The command line is broken down by whitespace, each piece gets a C-string, and a spot in argv[]
▸ argv[0] is always program name
▸ Example:
▸ ./prog1 4 0.5 10000
▸ ./zombies 20 2 10000 137957
41
CommandLineArguments• Nowwecanunderstandthearguments
passedtothemainfunction(int argc,char*argv[])
• Atthecommandpromptwecangiveinputstoourprogramratherthanmakingqueryingtheuserinteractively:– $./prog140.5100000– $cpbroke.c broke2.c
• Commandlinestringisbrokenatwhitespacesandcopiedintoindividualstringsandthenpackagedintoanarray(argv)
– Eachentryisapointertoastring(char*)
• Argc indicateshowlongthatarraysis(argv[0]isalwaystheexecutablename)
p r o g 1 4 0 . 5 1 0 0 0 0 0
p r o g 1 \0
4
0 . 5
1 0 0 0 0 0
\0
\0
\0
argv[0]argv[1]argv[2]argv[3]
Command line:
240240288300196
288
300
196
Linux shell command line
./prog1 Executable
int main(int argc, char *argv[])
argc = 4 argv = 5a0
5a0
TEXT
TYPICAL COMMAND LINE USAGE
▸ Twentyone assignment uses command line args
▸ At beginning of main(), check to see if argc is correct
▸ Implies the user put in the right # of arguments
▸ Remember, each argument is a C-string
▸ String arguments = OK
▸ Numeric arguments: need to convert
▸ int atoi() (ASCII to Int)
▸ double atof() (ASCII to Floating point)
42
CommandLineArguments
• Recommendedusage:– Uponstartupcheckargc tomakesurethe
userhasinputthedesirednumberofargs (remembertheexecutablecountsasoneoftheargs.)
• Problem:– Eachargumentisatextstring…for
numberswewantitsnumericrepresentationnotitsASCIIrepresentation
– cstdlib defines:atoi()[ASCIItoInteger]andatof()[ASCIItofloat/double]
– Eachofthesefunctionsexpectsapointertothestringtoconvert
#include <iostream>#include <cstdlib>using namespace std;
// char **argv is the same as char *argv[]int main(int argc, char **argv){int init, num_sims;double p;if(argc < 4){cout << "usage: prog1 init p sims" << endl;return 1;
}
init = atoi(argv[1]);p = atof(argv[2]);num_sims = atoi(argv[3]);
...
p r o g 1 \0
4
0 . 5
1 0 0 0 0 0
\0
\0
\0
argv[0]
argv[1]
argv[2]
argv[3]
42
CommandLineArguments
• Recommendedusage:– Uponstartupcheckargc tomakesurethe
userhasinputthedesirednumberofargs (remembertheexecutablecountsasoneoftheargs.)
• Problem:– Eachargumentisatextstring…for
numberswewantitsnumericrepresentationnotitsASCIIrepresentation
– cstdlib defines:atoi()[ASCIItoInteger]andatof()[ASCIItofloat/double]
– Eachofthesefunctionsexpectsapointertothestringtoconvert
#include <iostream>#include <cstdlib>using namespace std;
// char **argv is the same as char *argv[]int main(int argc, char **argv){int init, num_sims;double p;if(argc < 4){cout << "usage: prog1 init p sims" << endl;return 1;
}
init = atoi(argv[1]);p = atof(argv[2]);num_sims = atoi(argv[3]);
...
p r o g 1 \0
4
0 . 5
1 0 0 0 0 0
\0
\0
\0
argv[0]
argv[1]
argv[2]
argv[3]
TEXT
STRING FUNCTION LIBRARY▸ #include <cstring> gets you lots of useful C-string functions
▸ int strlen(char *dest);
▸ int strcmp(char *s1, char*s2);
▸ Return 0 if equal, >0 if s1 would come lexicographically before s2, <0 otherwise
▸ char* strcpy(char *dest, char *src);
▸ Copy src to dest
▸ char* strcat(char *dest, char *src);
▸ Copy src to the end of dst and NULL terminate. Aka concatenate src onto dest
▸ char* strchr(char *str, char c);
▸ Return a pointer to the first occurrence of c in str, NULL otherwise
TEXT
IN CLASS EXERCISES
▸ cmdargs_sum
▸ cmdargs_smartsum
▸ cmdargs_smartsum_str
▸ toi
TEXT
WHY USE POINTERS?
▸ To change a variable(s) local to one function in another function
▸ a.k.a. pass-by-pointer or pass-by-reference
▸ When using large data structures, pass by pointer avoids making copies
▸ Copies aren’t free: memory use and time
▸ When we need a variable address. We don’t know, or can’t know the address of a desired memory address at compile time
▸ Accessing embedded hardware registers
✔
✔
←
TEXT
DYNAMIC MEMORY - MOTIVATION
▸ Writing a program to calculate student grades.
▸ int scores[??];
▸ How many students?
▸ The following is bad form/unsupported
▸ int num; cin >> num; int scores[num];
▸ Also, variables declared on the stack die when that function finishes…
▸ How to solve this problem?
TEXT
DYNAMIC MEMORY - ANALOGY
▸ Public storage
▸ Need more space? Go rent a locker.
▸ Need more? Rent another.
▸ Had a garage sale, don’t need them any more?
▸ Terminate the lease.
▸ Locker becomes available to someone else
TEXT
DYNAMIC MEMORY
▸ Dynamic memory is on-demand-memory
▸ When you need some memory you allocate what you need
▸ This memory is allocated on the heap
▸ When you are done, you release it back to the heap
▸ Heap memory is visible (valid) any where in your program
▸ So any function with a pointer to heap-allocated memory can use it
TEXT
THE HEAP
▸ The heap is an area of memory that can grow/shrink as your program executes
▸ i.e. it is “dynamic”
▸ Stack grows towards lower addresses (up on the drawing)
▸ Heap grows towards higher addresses (down)
▸ In rare cases they collide - PANIC ENSUES
▸ or your program crashes
49
DynamicMemory&theHeap
• Codeusuallysitsatlowaddresses
• Globalvariablessomewhereaftercode
• Systemstack(memoryforeachfunctioninstance
thatisalive)
– Localvariables
– Returnlink(wheretoreturn)
– etc.
• Heap:Areaofmemorythatcanbeallocatedand
de-allocatedduringprogramexecution(i.e.
dynamicallyatrun-time)basedontheneedsof
theprogram
• Heapgrowsdownward,stackgrowsupward…
– Inrarecasesoflargememoryusage,theycould
collideandcauseyourprogramtofailorgenerate
anexception/error Memory
…
…
…
Code
Stack (area for
data local to a function)
Globals
0
…
Heap
fffffffc
TEXT
C++ DYNAMIC MEMORY ALLOCATION
▸ ‘new’ operator
▸ Use to allocate memory from the heap. Either single variables or arrays
▸ ‘new’ returns a pointer to the newly allocated memory
▸ The pointer is of the appropriate type
double *dptr = new double; //allocate 8 bytes to hold one double
int* array = new int[100]; //allocate an array of 100 integers
TEXT
C++ DYNAMIC MEMORY DEALLOCATION
▸ `delete` operator gives the memory back
▸ Delete is a misnomer! Nothing is deleted or zero’d out
▸ Calling `delete` on a pointer makes the memory available again, so it can be reused
▸ Note the syntax [] for arrays
delete dptr; //give back the 8 bytes
delete[] array; //give back the memory allocated for the entire array
TEXT
DYNAMIC MEMORY USAGE53
DynamicMemoryAllocationint main(int argc, char *argv[]){int num;
cout << “How many students?” << endl;cin >> num;
int *scores = new int[num];// can now access scores[0] .. scores[num-1];return 0;
}
Memory
20bc420bc820bcc20bd0
20bc0 0000000000
…
…
…Code
local vars
Globals
0
…
Heap
fffffffc
scores[0]
new allocates:
scores[4]
scores[1]scores[2]scores[3]
int main(int argc, char *argv[]){int num;
cout << “How many students?” << endl;cin >> num;
int *scores = new int[num];// can now access scores[0] .. scores[num-1];delete [] scoresreturn 0;
}
TEXT
DYNAMIC MEMORY CHECKPOINT
_________ data = new int;
_________ data = new char;
_________ data = new char[100];
_________ data = new char*[20];
_________ data = new string;
TEXT
DYNAMIC MEMORY CHECKPOINT
int* data = new int;
char* data = new char;
char* data = new char[100];
char** data = new char*[20];
string* data = new string;
TEXT
DYNAMIC MEMORY USAGE
▸ Dynamic Memory ‘lives’ on heap
▸ Only accessible with the pointer returned from new
56
DynamicAllocation• DynamicAllocation
– Livesontheheap• Doesn'thaveaname,onlypointer/addresstoit
– Livesuntilyou'delete'it• Doesn'tdieatendoffunction
(thoughpointertoitmay)
• Let'sdrawtheseasboxesintheheaparea
// Computes rectangle area, // prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, a;area(wid,len);
}
int* area(int w, int l){int* ans = new int;*ans = w * l;return ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
-73249515 a0xbf8
00400120 Return link
0xbfc
area 8 w0xbe4
5 l0xbe8
004000ca0 Return link
0xbec
0x93c ans0xbe0
Heap Area of RAM
400x93c
56
DynamicAllocation• DynamicAllocation
– Livesontheheap• Doesn'thaveaname,onlypointer/addresstoit
– Livesuntilyou'delete'it• Doesn'tdieatendoffunction
(thoughpointertoitmay)
• Let'sdrawtheseasboxesintheheaparea
// Computes rectangle area, // prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, a;area(wid,len);
}
int* area(int w, int l){int* ans = new int;*ans = w * l;return ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
-73249515 a0xbf8
00400120 Return link
0xbfc
area 8 w0xbe4
5 l0xbe8
004000ca0 Return link
0xbec
0x93c ans0xbe0
Heap Area of RAM
400x93c
56
DynamicAllocation• DynamicAllocation
– Livesontheheap• Doesn'thaveaname,onlypointer/addresstoit
– Livesuntilyou'delete'it• Doesn'tdieatendoffunction
(thoughpointertoitmay)
• Let'sdrawtheseasboxesintheheaparea
// Computes rectangle area, // prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, a;area(wid,len);
}
int* area(int w, int l){int* ans = new int;*ans = w * l;return ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
-73249515 a0xbf8
00400120 Return link
0xbfc
area 8 w0xbe4
5 l0xbe8
004000ca0 Return link
0xbec
0x93c ans0xbe0
Heap Area of RAM
400x93c
56
DynamicAllocation• DynamicAllocation
– Livesontheheap• Doesn'thaveaname,onlypointer/addresstoit
– Livesuntilyou'delete'it• Doesn'tdieatendoffunction
(thoughpointertoitmay)
• Let'sdrawtheseasboxesintheheaparea
// Computes rectangle area, // prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, a;area(wid,len);
}
int* area(int w, int l){int* ans = new int;*ans = w * l;return ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
-73249515 a0xbf8
00400120 Return link
0xbfc
area 8 w0xbe4
5 l0xbe8
004000ca0 Return link
0xbec
0x93c ans0xbe0
Heap Area of RAM
400x93c
Stack Heap
Memory Leak!
TEXT
MEMORY LEAKS
▸ You must keep track of heap allocated pointers!
▸ If you don’t, the memory “leaks”
▸ Allocated, but no way to deallocate
▸ Now this code can delete the memory when finished with it
58
DynamicAllocation• DynamicAllocation
– Livesontheheap• Doesn'thaveaname,onlypointer/addresstoit
– Livesuntilyou'delete'it• Doesn'tdieatendoffunction
(thoughpointertoitmay)
• Let'sdrawtheseasboxesintheheaparea
// Computes rectangle area, // prints it, & returns itint* area(int, int);void print(int);int main(){int wid = 8, len = 5, *a;a = area(wid,len);cout << *a << endl;delete a;
}
int* area(int w, int l){int* ans = new int;*ans = w * l;return ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
0x93c a0xbf8
00400120 Return link
0xbfc
Heap Area of RAM
400x93c
TEXT
POINTER TIP!▸ Never return a pointer to a local variable!
59
PointerMistake• Neverreturnapointertoalocalvariable // Computes rectangle area,
// prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, *a;a = area(wid,len);cout << *a << endl;
}
int* area(int w, int l){int ans;ans = w * l;return &ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
-73249515 a0xbf8
00400120 Return link
0xbfc
area 8 w0xbe4
5 l0xbe8
004000ca0 Return link
0xbec
40 ans0xbe0
Heap Area of RAM
59
PointerMistake• Neverreturnapointertoalocalvariable // Computes rectangle area,
// prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, *a;a = area(wid,len);cout << *a << endl;
}
int* area(int w, int l){int ans;ans = w * l;return &ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
-73249515 a0xbf8
00400120 Return link
0xbfc
area 8 w0xbe4
5 l0xbe8
004000ca0 Return link
0xbec
40 ans0xbe0
Heap Area of RAM
60
PointerMistake• Neverreturnapointertoalocalvariable• Pointerwillnowpointtodeadmemoryand
thevalueitwaspointingatwillbesooncorrupted/overwritten
• Wecallthisadanglingpointer(i.e.apointertobadordeadmemory)
// Computes rectangle area, // prints it, & returns itint* area(int, int);void print(int);
int main(){int wid = 8, len = 5, *a;a = area(wid,len);cout << *a << endl;
}
int* area(int w, int l){int ans;ans = w * l;return &ans;
}
Stack Area of RAM
8 wid0xbf0
main 5 len0xbf4
0xbe0 a0xbf8
00400120 Return link
0xbfc
Heap Area of RAM
TEXT
IN CLASS EXERCISE
▸ ordered_array
TEXT
MULTIDIMENSIONAL ARRAYS AND DYNAMIC MEMORY
▸ How to allocate 2D, 3D or more arrays?
▸ int* image = new int[x][y]; //This won’t compile
▸ Solution? Higher dimensions are allocated as pointers, only lowest dimension is data type.
▸ This is how the wordBank[] in lab 7 works.
TEXT
ALLOCATING MULTIDIMENSIONAL ARRAYS
▸ Example: allocate image array X, Yint** image = new int*[X];
for(int i=0;i<X;i++)
{
image[i] = new int[Y];
}
//Then the syntax to use is the same
image[i][j] = 0;
TEXT
ALLOCATING 3D EXAMPLE
▸ Allocate array sized X, Y, Zint*** array = new int**[X];
for(int i=0;i<X;i++)
{
array[i] = new int*[Y];
for(int j=0;j<Y;j++)
{
array[i][j] = new int[Z];
}
}
//now we can use it
array[1][2][3] = 0;