Title: Pointers to Pointers, Dynamic Multidimensional Arrays
1Pointers to Pointers,Dynamic Multidimensional
Arrays
Mar. 25, 2008
2News
- Week 10 source code password
- eagle
- Sign class list if you were here last Thursday!!
3Quiz
- What is an array? What is a static array? What
is a dynamic array? - What data type is x?
- int x
- How are addresses of elements in an array related
to one another? - Why does the address of a variable change each
time the same program runs? - What does malloc do again???
4Hacker's Tip Du Jour
- Does anyone in the class
- Have more than one computer?
- Have a computer with more than one CPU?
- Have a computer with a CPU with more than one
core? - Wouldn't it be great if we could use all this
processing power together for a single purpose?
5Distributed/Parallel Processing
- Suppose we were trying to find the largest number
stored in a super-gigantic array - The array is so big that it takes 25 minutes on
my laptop to go through the whole thing - If the whole class is working together as a team,
can we find it faster? - How?
6Break it down into chunks
int massiveArrayHugeNumber int
chunkSize HugeNumber / NumberStudents int
chunkNumber 0 int startIndex
chunkNumber chunkSize int endIndex
(chunkNumber 1) chunkSize int
maxNumberSeen -1 for( i startIndex i lt
endIndex i )? if( massiveArrayi gt
maxNumberSeen )? maxNumberSeen
massiveArrayi
7Distributed/Parallel Processing
8More Cores
- Today
- Dualcore/Quadcore chips are common and cheap
- PS3 has 8 cores -- 400
- Tomorrow
- Even more cores per chip
- 128 cores in the next few years
- 1000 cores within 10 or so years
- Booyah.
9Visual Array Memory
10A Simple Program
int x 15 int addressX x printf( x
is d\n, x ) printf( Address of x is p\n,
addressX )
11A Simple Program
A simple integer variable, x, and a variable that
stores x's address.
int x 15 int addressX x printf( x
is d\n, x ) printf( Address of x is p\n,
addressX )
12Inside Memory
13Inside Memory
Partially simplified address
14Inside Memory
x is stored in address 0x1 and has value 15.
15Inside Memory
addressX is stored in address 0x4 and has value
0x1.
16A Simple Program
int x 15 int addressX x printf( x
is d\n, x ) printf( Address of x is p\n,
addressX ) printf( Address of addressX is
p\n, addressX )
What do we get if we print out the address of
addressX???
17A Simple Program
int x 15 int addressX x printf( x
is d\n, x ) printf( Address of x is p\n,
addressX ) printf( Address of addressX is
p\n, addressX )
What would you say the data type of the address
of addressX is?
18Review Pointer Types
int x 15 int addressX x float y
3.1415 float addressY y char z 'w'
char addressZ z
19Review Pointer Types
int x 15 int addressX x float y
3.1415 float addressY y char z 'w'
char addressZ z
int means that the address being stored (pointed
to) contains an integer value.
20Review Pointer Types
int x 15 int addressX x float y
3.1415 float addressY y char z 'w'
char addressZ z
float means that the address being stored
(pointed to) contains a float value.
21Review Pointer Types
int x 15 int addressX x float y
3.1415 float addressY y char z 'w'
char addressZ z
char means that the address being stored
(pointed to) contains a char value.
22What type?
int x 15 int addressX x printf( x
is d\n, x ) printf( Address of x is p\n,
addressX ) printf( Address of addressX is
p\n, addressX )
So what type of value is being stored at addressX?
23What type?
int x 15 int addressX x printf( x
is d\n, x ) printf( Address of x is p\n,
addressX ) printf( Address of addressX is
p\n, addressX )
Another address is being stored there! This
address doesn't point to an int or float...it
points to another address.
24Double Stars
int x 15 int addressX x int
addressOfAddressX addressX printf( x is
d\n, x ) printf( Address of x is p\n,
addressX ) printf( Address of addressX is
p\n, addressOfAddressX )
25Double Stars
int x 15 int addressX x int
addressOfAddressX addressX printf( x is
d\n, x ) printf( Address of x is p\n,
addressX ) printf( Address of addressX is
p\n, addressOfAddressX )
Now we have 2 stars! This means that this
address points to another address. Will we ever
need 3 stars??? No, thank goodness, 2 levels of
indirection are enough.
26Dynamically-Sized Multidimensional Arrays
27Using Double Stars
- Why would we ever need to use double stars?
- I have to admit it seems a little bit ridiculous
when you first see it - What did we use a single star for?
- Dynamic arrays created with malloc
28Using Double Stars
- Double stars will also help us do cool things
with malloc - They're tricky, but useful
- Now we can make a multidimensional array that has
a dynamic number of rows and columns! - This will help us get exactly the size of array
that we need.
29Our Multidimensional Friends
30Static Multidimensional Array
int xNumberRowsNumberColumns
Use square brackets to statically size the
multidimensional array of integers. NumberRows
and NumberColumns are defined constants.
31Dynamic Multidimensional Arrays
- Building dynamically-sized multidimensional
arrays is a bit trickier - Basic Idea for an int array
- Declare an int double star variable
- This is the name of your multidimensional array
- Use malloc to to get an array of int variables
- You need one int per row of the array
- Use a loop with malloc inside to allocate the
space for the number of columns per row - This malloc will get an array of int variables
32Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
33Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
Start with a double star variable. This is the
top-level address/pointer to your
multidimensional array.
34Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
Start by doing a single malloc that allocated
space for the number of rows.
35Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
NumberRows can be any value...we could easily do
a scanf and ask the user to enter how many rows
are wanted.
36Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
We use int here because each element of the
top-level array will be an address...the address
of where that row's values are stored.
37Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
Make sure you check if malloc succeeded by
checking if myArray NULL. The check is
omitted here for space considerations.
38Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
Set up a loop that goes through the number of
rows, one at a time.
39Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
For each row, use malloc to allocate space for
the elements of that row. Each element is a
normal int data type and you have NumberColumns
of them.
40Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
We store the address given by malloc in
myArrayi because myArrayi holds the address
of the ith row array.
41Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
We need the check for NULL for each malloc, so it
goes inside the loop as well.
42Dynamic Multidimensional Array
int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc( NumberColumns
sizeof( int ) ) // Check if malloc
suceeded
Once the loop is finished, we now have a normal,
multidimensional array ready to be used. We can
use it just like a statically-sized array. To
set the value at row 1, column 1 myArray00
10
43Freeing a Multidimensional Array
... for( i 0 i lt NumberRows i)?
free( myArrayi ) free( myArray )
44Freeing a Multidimensional Array
... for( i 0 i lt NumberRows i)?
free( myArrayi ) free( myArray )
Remember the rule of freeing memory 1 free for
every 1 malloc. We had 1 malloc for each row and
1 more malloc for the list of rows. When the
program is done we have to free those up.
45Freeing a Multidimensional Array
... for( i 0 i lt NumberRows i)?
free( myArrayi ) free( myArray )
Set up a loop to free the rows, one by one.
46Freeing a Multidimensional Array
... for( i 0 i lt NumberRows i)?
free( myArrayi ) free( myArray )
Each time you use free, another row array is
freed up. We have to index with i here to say
which row we want freed.
47Freeing a Multidimensional Array
... for( i 0 i lt NumberRows i)?
free( myArrayi ) free( myArray )
Once all the rows are freed, then the top-level
array can be freed. Remember that this one held
the list of row addresses. Make sure you don't
free this one before freeing the rows.
48Multidimensional Table in Memory
49 int myArray myArray malloc(
NumberRows sizeof( int ) ) // Check if
malloc succeeded for( i 0 i lt NumberRows
i )? myArrayi malloc(
NumberColumns sizeof( int ) ) // Check
if malloc suceeded
50Ragged-Edged Tables
51Normal, Rectangular Table
- The table in the last example had the same number
of elements (NumberColumns) in each row -
52Rectangular Table
- for( i 0 i lt NumberRows i )?
-
- myArrayi malloc( NumberColumns sizeof(
int ) ) - // Check if malloc suceeded
The number of elements in each row was the same
NumberColumns. So each row was the same size.
53Ragged-Edged Table
- What if we want to have a different number of
elements in each row?
54Ragged-Edged Table
- How could we make a ragged-edged table with a
statically-sized multidimensional array? - int myArrayNumberRows????
55Building a Ragged-Edged Table
- for( i 0 i lt NumberRows i )?
-
- myArrayi malloc( ??? sizeof( int ) )
- // Check if malloc suceeded
Any number can go here! It can change each time
through the loop.
56Dynamic Arrays of Strings
57Arrays of Strings
- Arrays of strings are the perfect use of
ragged-edged tables - Each string in the array may be a different
length - E.g. Suppose we wanted to store the names of all
the NCAA basketball players in a list
58Ragged List of Strings
59List/Array of Strings (part1)?
char playerNames char tempNameMaxStringLen
gth int numberPlayers int i 0
printf( How many players? ) scanf( d,
numberPlayers ) playerNames malloc(
numberPlayers sizeof( char ) ) // Check if
malloc succeeded
60List/Array of Strings (part1)?
char playerNames char tempNameMaxStringLen
gth int numberPlayers int i 0
printf( How many players? ) scanf( d,
numberPlayers ) playerNames malloc(
numberPlayers sizeof( char ) ) // Check if
malloc succeeded
char will give us the top-level name for a
multidimensional array of characters.
61List/Array of Strings (part1)?
char playerNames char tempNameMaxStringLen
gth int numberPlayers int i 0
printf( How many players? ) scanf( d,
numberPlayers ) playerNames malloc(
numberPlayers sizeof( char ) ) // Check if
malloc succeeded
We'll use a statically-size temporary string to
store the name typed in by the user each time.
We'll check the length of each entered name and
only malloc enough memory to store that name.
62List/Array of Strings (part1)?
char playerNames char tempNameMaxStringLen
gth int numberPlayers int i 0
printf( How many players? ) scanf( d,
numberPlayers ) playerNames malloc(
numberPlayers sizeof( char ) ) // Check if
malloc succeeded
Prompt the user to enter the number of player
names to enter. Store the result in
numberPlayers.
63List/Array of Strings (part1)?
char playerNames char tempNameMaxStringLen
gth int numberPlayers int i 0
printf( How many players? ) scanf( d,
numberPlayers ) playerNames malloc(
numberPlayers sizeof( char ) ) // Check if
malloc succeeded
Now that we know how many players are going to be
entered, we can use malloc to get the row
pointers.
64List/Array of Strings (part1)?
char playerNames char tempNameMaxStringLen
gth int numberPlayers int i 0
printf( How many players? ) scanf( d,
numberPlayers ) playerNames malloc(
numberPlayers sizeof( char ) ) // Check if
malloc succeeded
We use char for the data type because each row
element will be a string itself.
65List/Array of Strings (part2)?
for( i 0 i lt numberPlayers i )?
printf( Enter name player d, i1 )
sgets( tempName, MaxStringLength, stdin )
length strlen( tempName ) playerNamesi
malloc( ( length 1) sizeof( char ) ) //
Check if malloc succeeded here strncpy(
playerNamesi, tempName, MaxStringLength )
66List/Array of Strings (part2)?
for( i 0 i lt numberPlayers i )?
printf( Enter name player d, i1 )
sgets( tempName, MaxStringLength, stdin )
length strlen( tempName ) playerNamesi
malloc( ( length 1) sizeof( char ) ) //
Check if malloc succeeded here strncpy(
playerNamesi, tempName, MaxStringLength )
Prompt for each name.
67List/Array of Strings (part2)?
for( i 0 i lt numberPlayers i )?
printf( Enter name player d, i1 )
sgets( tempName, MaxStringLength, stdin )
length strlen( tempName ) playerNamesi
malloc( ( length 1) sizeof( char ) ) //
Check if malloc succeeded here strncpy(
playerNamesi, tempName, MaxStringLength )
Use sgets (or fgets) to grab the player's name.
Store it in the statically-sized tempName
variable.
68List/Array of Strings (part2)?
for( i 0 i lt numberPlayers i )?
printf( Enter name player d, i1 )
sgets( tempName, MaxStringLength, stdin )
length strlen( tempName ) playerNamesi
malloc( ( length 1) sizeof( char ) ) //
Check if malloc succeeded here strncpy(
playerNamesi, tempName, MaxStringLength )
Malloc space for this name in the playerNames
array. Just get enough room for the entered
name. Add 1 to the length for the null
terminator.
69List/Array of Strings (part2)?
for( i 0 i lt numberPlayers i )?
printf( Enter name player d, i1 )
sgets( tempName, MaxStringLength, stdin )
length strlen( tempName ) playerNamesi
malloc( ( length 1) sizeof( char ) ) //
Check if malloc succeeded here strncpy(
playerNamesi, tempName, MaxStringLength )
Finally, copy the name in tempName over into the
playerNames array at position i.