Title: Pointers, Variables, and Memory
1Pointers, Variables, and Memory
2Variables and Pointers
- When you declare a variable, memory is allocated
to store a value. A pointer can be used to hold
the address to a chunk of memory. - The operator is used to return a variables
memory address - int intVar // allocate memory by //
declaring a variable - cout ltlt "Address " ltlt intVar ltlt endl
3Variables and Pointers
- A pointer variable is used to hold an address to
a memory location. A pointer variable has a type
associated with it, and the memory address it
points to, should hold data of that type - int myInt 0 // Allocates memory, stores 0
- int pMyInt // Declares an empty pointer //
variable
4Dereferencing Pointers
- If we want to set or get the value that is stored
at the memory address in the pointer then we have
to use operator - int myInt 0 //Allocates memory, stores 0
- int pMyInt //Declares an empty pointer
- pMyInt myInt //Puts address in the ptr
5Dereferencing Pointers
- If we want to set or get the value that is stored
at the memory address in the pointer then we have
to use operator - int myInt 0 //Allocates memory, stores 0
- int pMyInt //Declares an empty pointer
- pMyInt myInt //Puts address in the ptr
- pMyInt 5 //puts 5 into myInt
6Dereferencing Pointers
- If we want to set or get the value that is stored
at the memory address in the pointer then we have
to use operator - int myInt 0 //Allocates memory, stores 0
- int pMyInt //Declares an empty pointer
- pMyInt myInt //Puts address in the ptr
- pMyInt 5 //puts 5 into myInt
- cout ltlt myInt ltlt endl //Prints 5
- cout ltlt pMyInt ltlt endl //Also prints 5
- cout ltlt pMyInt ltlt endl //What prints?
variable name
value
memory address
3000
myInt
3004
5
3004
pMyInt
3008
3012
7Where are the errors?
- int main()
- int m
- int pm
- pm 5
- int n
- int pn n
- pn 5
8Where are the errors?
- int main()
- int m
- int pm
- pm 5
- int n
- int pn n
- pn 5
ERROR! No address in pm
//Correction pm m pm 5
9Where are the errors?
- int main()
- int m
- int pm
- pm 5
- int n
- int pn n
- pn 5
ERROR! No address in pm
//Correction pm m pm 5
ERROR! Missing operator
//Correction pn 5
10Pointers Arrays
-
- Pointers are simply, by definition, variables
that hold addresses. A name of an array also
holds the address of the first element in the
array. This value cannot change. Therefore, an
array name can be considered to be a pointer
constant.
11Pointers Arrays
- const int CAPACITY 5
- int myArrayCAPACITY //Declare an array
- cout ltlt myArray //Prints its address
- for( int i0 iltCAPACITY i )
- myArrayi i //initialize the elements
- cout ltlt myArray ltlt endl //Prints 0
- cout ltlt myArray0 ltlt endl //Prints 0
0
1
2
3
4
myArray
0
1
2
3
4
12Pointer Arithmetic
- Pointer arithmetic allows a few arithmetic
operators for manipulating the addresses in
pointers. - In an array a, a is a constant pointer to the
first element and a1 is a constant to the second
element. In the same way, if p points to the
second element in an array, then p-1 point to the
preceding element in that array, and p1 points
to the succeeding element.
13Pointer Arithmetic
- int a5 2, 4, 6, 8, 10
- int p
- p a1
- cout ltlt a0 ltlt ", " ltlt p-1ltlt ", " ltlt (p -
1) ltlt endl - cout ltlt a1 ltlt ", " ltltp0ltlt ", " ltlt (p) ltlt
endl - cout ltlt a2 ltlt ", " ltlt p1ltlt ", " ltlt (p 1)
ltlt endl -
- Output
- 2, 2, 2
- 4, 4, 4
- 6, 6, 6
14Incrementing and Decrementing Addresses with
Postfix and Prefix Operators
- Adding 1 to a pointer causes the pointer to
point to the next element of the type being
pointed to. Therefore p should point to the
next element. - However, when a combination of indirection and
postfix operators are used ( as is often done),
use the precedence table to figure out what gets
executed first. Postfix operators have higher
precedence than the indirection operator.
15Incrementing and Decrementing Addresses with
Postfix and Prefix Operators
- int p
- int a5 12, 4, 16, 98, 50
- p a
- cout ltlt (p) ltlt endl // prints 12
- cout ltlt p ltlt endl // print 4
- cout ltlt p ltlt endl // prints 16
- cout ltlt p ltlt endl // prints 16
- cout ltlt (p)-- ltlt endl // prints 16
- cout ltlt p ltlt endl // prints 4
- cout ltlt --p ltlt endl // prints 12
- cout ltlt p ltlt endl // prints 12
Is this the same as p?
Is this the same as (--p) ?
16Dynamically Allocating Arrays
- An array can be created dynamically with new
- new allocates a section of memory for the
array, and then returns a pointer to it. - This is a major advantage when you dont know how
large the array will be until the program is
running - int capacity, myData
- cin gtgt capacity
- myData new intcapacity//Creates the array
- for( int i0 iltcapacity i ) //Initialize it
- myDatai i
- cout ltlt myData0 ltlt endl //Prints 0
- delete myData
17Using delete
- Memory allocated with new must always be
recovered by delete - Always delete an array when you dont need it
anymore if you created it with new - delete myData
18Function Arguments
- The variables that are used to pass data into a
function or to return results - Example
- bool isPalindrome( string forw, string rev )
- if( forw rev )
- return true
-
- Arguments can be passed
- By value the default in C
- By reference
arguments or parameters
function name
return type
19Passing Arguments by Value
- Used to pass data only into a function
- When a variable is passed by value, a copy of it
is made inside the function. The copy is
destroyed when the function returns. - Example passing an argument by value
- void noChange( int n )
- n n n
-
- int main()
- int num 5
- noChange( num )
- cout ltlt num ltlt endl //prints 5
20Reference Argument
- Syntax
- int count
- Indicates that an alias for the argument is used
inside the function
21Using References
- Used primarily for function arguments to
implement passing by reference - Advantage Efficiency
- Passing variables to functions by reference is
very useful if you want to change or update a
variable through a function. - If your variable is a relatively large variable,
or a whole class or struct or array, it is always
advisable to pass the variable by reference since
big amounts of data need not be copied when
evaluating them.
22Passing Arguments by Reference
- include ltiostreamgt
- void Square(int pVal)
- main()
- int Number10
- printf("Number is d\n", Number)
- Square(Number)
- printf("Number is d\n", Number)
-
- void Square(int pVal)
- pVal pVal
- printf("Number is d\n", pVal)
-
23Passing Arguments by Pointer
- include ltiostreamgt
- void Square(int pVal)
- main()
- int Number10
- printf("Number is d\n", Number)
- Square(Number)
- printf("Number is d\n", Number)
-
- void Square(int pVal)
- pVal pVal
- printf("Number is d\n", pVal)
-
24Reference vs. Pointers
- References cannot be re-assigned. They are like
constant pointers. - A good rule of the thumb is to use references
when you can, and pointers when you have to -
25Passing an Array to a Function
- Since an array name is actually a pointer to its
first element, when an array is passed to a
function, an address operator is not needed. - int findMax ( int , int )
- int main()
-
- int a5 12, 4, 16, 98, 50
- cout ltlt "The maximum value is " ltlt findMax(a, 5)
ltlt endl - return 1
-
- int findMax ( int vals, int numElem )
-
- int max vals0
- for (int i1 iltnumElem i )
- if (max lt valsi )
- max valsi
- return max
-
26Passing an Array to a Function
- However, since an address is actually passed,
the code can also be written thus - int findMax ( int , int )
- int main()
-
- int a5 12, 4, 16, 98, 50
- cout ltlt "The maximum value is " ltlt findMax(a, 5)
ltlt endl - return 1
-
- int findMax ( int vals, int numElem )
-
- int max vals0
- for (int i1 iltnumElem i )
- if (max lt valsi )
- max valsi
- return max
-
27Passing an Array to a Function
- Here are two other versions of findMax, this
time using pointers instead of array subscripts - int findMax ( int vals, int numElem )
-
- int max vals
- for (int i1 iltnumElem i )
- if (max lt (vals i) )
- max (vals i)
- return max
28Passing an Array to a Function
- int findMax ( int vals, int numElem )
-
- int max vals // gets the first element and
- // then increments
- for (int i1 iltnumElem i, vals )
- if (max lt vals )
- max vals
- return max
29Dynamically Allocated structs
- We can dynamically create a structure with new
- Use new to allocate memory and return a pointer
- Person pDonald new Person
- When a pointer is used to set values stored in a
structure, each field must be accessed by the
-gt operator - pDonald-gtID 1005
- pDonald-gtfirstName "Donald"
- pDonald-gtlastName "Knuth"
- cout ltlt pDonald-gtfirstName ltlt endl
- delete pDonald//Always delete after new
- Optional syntax cout ltlt (pDonald).firstName
30Dynamic Memory Allocation
- Data structures that use arrays, structs, and
objects to store their data often use dynamic
memory allocation to create the storage space - More efficient
- We dont need to know in advance how much space
to set aside - Pointers can be passed to functions more
efficiently because pointer parameters are passed
by reference
31Struct Constructors
- Creating a structure that initializes itself
- struct Person
- int ID
- string name
- Person(int i 0000, string n "Adam")
- ID(i), name(n)
-
- Constructor is called whenever a Person is
declared - Person adam//Default values used
- cout ltlt adam.name ltlt endl//Prints Adam
- Person david(1002,"David")//Arguments used
- Person pFrank new Person//Default values used
- pFrank-gtname "Frank"
Parameter
Default value
Initializer list
Constructor name