2020-09-30
Addresses and pointers
2
ECE 150 Fundamentals of Programming
Outline
• In this lesson, we will:
– Revisit the concept of an address
– Consider how to store them
– Look at some examples and naming conventions
– Understand the size of addresses
Addresses and
pointers
Douglas Wilhelm Harder, M.Math. LEL
Prof. Hiren Patel, Ph.D., P.Eng.
Prof. Werner Dietl, Ph.D.
© 2018 by Douglas Wilhelm Harder and Hiren Patel.
Some rights reserved.
Addresses and pointers Addresses and pointers
3 4
Addresses Addresses
• Recall that we have seen that • The different integer types store various numbers of bits:
– Memory is byte addressable Type Bits
• Every byte has a separate address
unsigned char 8 PIC 10F200
• It is convenient to represent these addresses using hexadecimal
unsigned short 16
– The size of an address is fixed for a specific processor
unsigned int 32 Intel 486
• Most general processors have 64-bits addresses
• Microcontrollers generally have up to 32-bit addresses unsigned long 64 Most computers today…
• The PIC 10F200 microcontroller has 8-bit addresses
– It costs less than 50¢
– Question: Can we not just store an address?
1
2020-09-30
Addresses and pointers Addresses and pointers
5 6
Addresses Addresses
• We could have a primitive data type 'address_t': • Problem: We have an address, but what is there?
int main() { – Is it an int?
int array[10]; – Is it a double or a float?
address_t addr_array{ array };
int main() {
// The variable 'addr_array' is now stores int array_a[10];
// the address of 'array' double array_b[10];
address_t addr_a{ array_a };
// These should print the same value address_t addr_b{ array_b };
std::cout << array << std::endl;
std::cout << addr_array << std::endl; // ...
// Carry on...
return 0;
}
Addresses and pointers Addresses and pointers
7 8
Addresses Address of variables
• C++ has a solution to this: • Question: What about local variables or parameters?
– A variable (local or parameter) is declared to be the “address of an – They, too, must have addresses…how can we find those addresses?
int” or the “address of a double” by prefixing an asterisks to the – The unary & operator returns the address of the operand
identifier void f( int n );
int main() {
void f( int n ) {
int array_a[10];
double a;
double array_b[10]; long b[10];
int *addr_a{array_a}; // 'addr_a' is a variable std::cout << "The address of the parameter 'n' is "
<< &n << std::endl;
// that stores the address std::cout << "The address of the local variable 'a' is "
// of an 'int' << &a << std::endl;
std::cout << "The address of the local array 'b' is "
<< b << std::endl;
double *addr_b{array_b}; // 'addr_b' is a variable
}
// that stores the address The address of the parameter 'n' is 0x7fff725f073c
// of a 'double' The address of the local variable 'a' is 0x7fff725f0798
The address of the local array 'b' is 0x7fff725f0740
2
2020-09-30
Addresses and pointers Addresses and pointers
9 10
Address of variables Pointers
• Similarly, we can assign these addresses to variables • A variable that stores an address is referred to as a pointer
void f( int n ); – Suppose you see:
double *p_var{};
void f( int n ) {
you may describe the variable p_var as either
double a;
long b[10];
“a variable that stores the address of a double”
int *p_n{ &n }; Output: “a pointer to a double”
double *p_a{ &a }; 0x7fff725f073c
long *p_b{ b }; 0x7fff725f0798
• To be absolutely clear to the reader,
0x7fff725f0740
std::cout << p_n << std::endl;
all pointer identifiers will be prefixed with 'p_'
std::cout << p_a << std::endl; – This is a naming convention widely used in industry
std::cout << p_b << std::endl; – We will use this naming convention in this course
}
Addresses and pointers Addresses and pointers
11 12
Size of a pointer How do we access what is at that address?
• Question: You are compiling code for a processor and you ask • Suppose you have an address
yourself “How many bytes is an address on this processor?” int *p_datum{ &n };
– Solution: • Question: How do we access the integer stored at that address?
std::cout << sizeof( int * ) << " bytes" << std::endl; – Solution: Prefix the identifier with an asterisk
int main() { Output:
• It doesn’t matter which type you pick: bool, int, double, short int n{ 42 }; 0x7fff725f073c
• On the computer eceubuntu, we get the output of 8 bytes or 64 bits int *p_datum{ &n }; 42
– It is unlikely any of you will get anything else 100 == 100
std::cout << p_datum << std::endl; 99 == 99
unless you have access to your parent’s laptop or desktop
std::cout << *p_datum << std::endl;
*p_datum = 100;
std::cout << *p_datum << " == " << n << std::endl;
n = 99;
std::cout << *p_datum << " == " << n << std::endl;
return 0;
}
3
2020-09-30
Addresses and pointers Addresses and pointers
13 14
Why pointers? Making sense of C++ declarations
• Why do we need to store addresses? • Consider these declarations:
– Arrays are fixed in their size: int n;
• What if you have to change an array? int array[10];
– Local variables and parameters are out of scope as soon as a int *p_datum;
function returns
int gcd( int m, int n );
• What if we require memory that continues to exist outside the scope
of a given function?
For n, to get an integer value, you must use n
For array, to get an integer value, you must use array[ n ]
For p_datum, to get an integer value, you must use *p_datum
For gcd, to get an integer value, you must call gcd( n1, n2 )
This was the original C design
Unfortunately, this doesn’t work for int &n;
Addresses and pointers Addresses and pointers
15 16
Capacity of an array? Capacity of an array?
• Up to now, we have indexed arrays with int: • The type of an index into an array depends on the processor
char array[100]; – For 8-bit processors, we could use unsigned char
for ( unsigned int k{0}; k < 100; ++k ) { – For 32-bit processors, we could use unsigned int
array[k] = '\0'; – For 64-bit processors, we should use unsigned long
}
• With a 64-bit computer, we could declare a much larger array: • Fortunately, there is a universal solution:
char array[10000000000]; – The type std::size_t is always guaranteed to be an unsigned
integer that can store the maximum index for a particular processor
for ( unsigned int k{0}; k < 10000000000; ++k ) {
array[k] = '\0';
• From now on,
}
if the purpose of a local variable is to index into an array,
it will be declared to be of type std::size_t
– Problem: the maximum int is 232 – 1 or approximately 4 billion
4
2020-09-30
Addresses and pointers Addresses and pointers
17 18
Summary References
• Following this lesson, you now [1] https://en.wikipedia.org/wiki/Pointer_(computer_programming)
– Understand the concept of addresses and storing them
– Know how to access the address of data in memory
– Know how to access and manipulate data at a memory location
– Understand the size of addresses on different computer
architectures
– You know about std::size_t
Addresses and pointers Addresses and pointers
19 20
Colophon Disclaimer
These slides were prepared using the Georgia typeface. Mathematical These slides are provided for the ECE 150 Fundamentals of
equations use Times New Roman, and source code is presented using Programming course taught at the University of Waterloo. The
Consolas. material in it reflects the authors’ best judgment in light of the
information available to them at the time of preparation. Any reliance
The photographs of lilacs in bloom appearing on the title slide and on these course slides by any party for any other purpose are the
accenting the top of each other slide were taken at the Royal Botanical responsibility of such parties. The authors accept no responsibility for
Gardens on May 27, 2018 by Douglas Wilhelm Harder. Please see damages, if any, suffered by any party as a result of decisions made or
actions based on these course slides for any other purpose than that for
https://www.rbg.ca/ which it was intended.
for more information.