CIS2500 Lab Three
The purpose of today’s lab is to review key concepts related to dynamic memory allocation in C.
Overview
Everything you write in C lives in memory. This includes data types, functions, and the very programs themselves. In order for your program to run it must be compiled, assembled, and linked with other source code in such a way that CPU instructions and memory locations are known at at runtime. C, as with all programming languages to various extents, provides mechanisms to abstract this process and a tool-chain to facilitate it.
Pass By Value & Pass By Reference
Library Analogy
Suppose that you went to the library with the intent of checking out some books. You walk up to the help desk with a list of 10 entries. You say to the librarian, “Hey book lady, give me these books”. Based on how the librarian choses to interpret this, one of three things happens:
1: She gives you 10 books
Now you have 10 books, how are you supposed to carry these? They probably wont fit in your bag, and even if they could, would you really want to be holding that many books around?
2: She gives you index cards with references to the 10 books
Okay, well these are definitely a lot easier on your back, so thats a nice. But wait, you can’t exactly do your book report on a bunch of Dewey Decimal numbers scribbled on some paper.
3: You Get Something In Between…
What you probably expected was a mix between the two. Maybe to get the few that where available and references to those which were checked out for later? Maybe to get 2 or 3 at a time? Whatever the case may be, this is largely left up to chance or the library’s policy, both of which you cannot control and may not be aware or ahead of time.
Making the Connection
- a physical book: value
- index card: reference
- your backpack: memory
- the librarian: system
Value
- implied in C when you initialize a variable without a pointer
*
- ie.
int count
- ie.
char letter
- ie.
- the size of the type is stored in memory
- ie. if a
double float
is 64 bits, 64 bits is reserved in memory
- ie. if a
- when values are passed as parameters, a local copy is made
- this prevents the modification of the passed variable
Reference
- implied in C when you initialize a variable with a pointer
*
or as an array[]
-ie.int *counts
-ie.char sentence[10]
- the size of pointer is stored in memory (an int)
- ie. if a
double float
is 64 bits, the size of an int, ie. 32 bits is stored in memory
- ie. if a
- when references are passed as parameters, the actual location of the value is provided
- this allows for the modification of the passed variable
Referencing/ Dereferencing
- you can get the value of a pointer by prefixing it with a pointer
*
or array notation- ie.
char myName[10] = "Jessy";
- to get the first character:
myName[0] == 'J'
*myName == 'J'
- to get the second character:
myName[1] == 'e'
*(myName+1) == 'e'
- take care using pointer arithmetic
- ie.
- you can get the address of a value by prefixing an ampersand
&
Task One: We Need to Talk About Your Grades..
Examine the following code.
#include <stdio.h>
#include <stdlib.h>
/**
* grade1.c
*
* This program will allocate memory for an integer on the stack, and
* demonstrate how C treats values passed by value as opposed to by reference.
*/
int finalGradeValue (int grade, int bonus); //grade passed by value
int finalGradeReference (int* grade, int bonus); //grade passed by reference
int main() {
int grade = 45;
finalGradeValue (grade, 5); // passed value not modified
printf ("Your final mark is %d. ", grade);
puts (grade < 50 ? "You failed!" : "You passed!");
finalGradeReference (&grade, 5); // passed value modified, notice '&'
printf ("Your final mark is %d. ", grade);
puts (grade < 50 ? "You failed!" : "You passed!");
return 0;
}
int finalGradeValue (int grade, int bonus) {
grade = grade + bonus;
return grade;
}
int finalGradeReference (int* grade, int bonus) {
*grade = *grade + bonus;
return *grade;
}
Questions
- How does it work?
- What will the output be?
- Why?
The Stack
When you declare and/or initialize a variable within a block, C reserves the amount of memory required to store that value in a region of memory called the stack.
- this is an area of memory which is managed by the system
- cannot be allocated or freed by a user program
- has a finite space
- written in contiguous blocks and is fast to access
- facilitates reentry
The Heap
When you want to allocate memory yourself, this is done on the heap. This is a much larger of memory which is only limited by the system’s available storage. User programs can allocate memory in C using malloc
, calloc
, and realloc
, and release it using free
, all of which are provided by stdlib.h
.
- this is an area of memory which is managed by the user, however monitored by the system
realloc
is not to be used in this course or for assignment 2
Task Two: Grades List Take Two
Rewrite our grade checking program, this time storing the grade integer in the heap.
The Rules
- declare grade as
int *grade
- allocate memory for grade using malloc or calloc
- free whatever memory you used
Hints
- you should only have to change 1 or two lines of code and dereference a couple of variables in main
- no need to modify the helper functions