Date post: | 01-Jan-2016 |
Category: |
Documents |
Upload: | barry-palmer |
View: | 22 times |
Download: | 1 times |
CS 1312CS 1312
Introduction to
Object Oriented Programming
Lecture 25
C & Pointers
Structs
Preprocessing
Bits, Bytes and WordsBits, Bytes and Words
• A bit is a binary digit which can have a value of 0 or 1• A byte today is normally considered to be 8 bits but
was originally designated as the smallest addressable unit of memory – Thus one could instruct the computer to store or retrieve a
given byte but not a given bit.
• Bytes may be grouped into words (e.g. 4 bytes)– (plus all kinds of zany combinations thereof like half-words,
double words, etc.)
• So words are addressed in multiples of 4– Since the bytes are addressed by one.
Conceptual MemoryConceptual Memory
• Each memory cell thus has two associated numbers– Its address– Its contents
• When using any symbolic language we can also associate a symbol or identifier
• Example
Memory Address Contents Symbol
or Identifier
2000 7 someInt
We write:int someInt;someInt = 7;
We write:int someInt;someInt = 7;
Conceptual MemoryConceptual Memory
Memory Address Contents Symbol
or Identifier
2000 7 someInt
Technically this only
exists up
through compilation.
Strictly SpeakingStrictly Speaking
• The computer has no idea what we’re actually doing (exception see HAL in 2001)
• So a given memory location such as a byte only has a limited number of possible values
• Byte: 0 - 255 (00 - FF16)
• It is the programmer using a programming language that can assign this byte a meaning– Unsigned numbers from 0 to 255– Signed numbers from -128 to 127– Characters from a typical encoding such as ASCII where for
example the letter ‘A” is represented by the number 65
• Thus we could also store in memory the address of any memory location. This is known as a pointer.
More MemoryMore Memory
ADDR CONT SYMB
1000 2000 pint
2000 7 ix
2004 42 iy
2008 -17 iz
• Notes:– The SYMB column isn’t
actually stored in memory.
– In fact, neither is the column marked ADDR!
– Assume that we are showing words (32 bits)
– Assume ints take a word
Initializing ItInitializing It
ADDR CONT SYMB
1000
2000 7 ix
2004
2008
• The codeint ix = 7;
Note: Where the actual values get stored depends on several factors. Since we deal with the symbols, we don’t worry about this most of the time.
Note: Where the actual values get stored depends on several factors. Since we deal with the symbols, we don’t worry about this most of the time.
Assigning to itAssigning to it
ADDR CONT SYMB
1000
2000 7 ix
2004 ? iy
2008 ? iz
• The codeint ix = 7;
int iy, iz;
Assigning to itAssigning to it
ADDR CONT SYMB
1000
2000 7 ix
2004 42 iy
2008 ? iz
• The codeint ix = 7;
int iy, iz;
iy = 42;
Assigning to itAssigning to it
ADDR CONT SYMB
1000
2000 7 ix
2004 42 iy
2008 -17 iz
• The codeint ix = 7;
int iy, iz;
iy = 42;
iz = iy - 59;
A Pointer at last!A Pointer at last!
ADDR CONT SYMB
1000 pint
2000 7 ix
2004 42 iy
2008 -17 iz
• The codeint *pint;
Possible Points of Confusion1. The pointer is named pint not
*pint2. It is not necessarily the size
of an int rather it is pointing to an int. Important in a minute.
Possible Points of Confusion1. The pointer is named pint not
*pint2. It is not necessarily the size
of an int rather it is pointing to an int. Important in a minute.
Can also be written as... int* pint
Make it point!Make it point!
ADDR CONT SYMB
1000 2000 pint
2000 7 ix
2004 42 iy
2008 -17 iz
• The codeint *pint;
pint = &ix;
DereferencingDereferencing
ADDR CONT SYMB
1000 2000 pint
2000 8 ix
2004 42 iy
2008 -17 iz
• The codeint *pint;
pint = &ix;
*pint = 8;
Syntax Note
int *pint;
Means that when pint is dereferenced it will be pointing
to an int
Syntax Note
int *pint;
Means that when pint is dereferenced it will be pointing
to an int
DereferencingDereferencing
ADDR CONT SYMB
1000 2000 pint
2000 50 ix
2004 42 iy
2008 -17 iz
• The codeint *pint;
pint = &ix;
*pint = 8;
*pint += iy;
Fasten Your Seat Belt!Fasten Your Seat Belt!
ADDR CONT SYMB
1000 ???? pint
2000 50 ix
2004 42 iy
2008 -17 iz
• The codeint *pint;
pint = &ix;
*pint = 8;
*pint += iy;
pint += 1;
was 2000
Fasten Your Seat Belt!Fasten Your Seat Belt!
ADDR CONT SYMB
1000 2004 pint
2000 50 ix
2004 42 iy
2008 -17 iz
• The codeint *pint;
pint = &ix;
*pint = 8;
*pint += iy;
pint += 1;
Why do they call it notorious pointer
arithmetic?
Why do they call it notorious pointer
arithmetic?
Pop QuizPop Quiz
int x, y;
int *px = &x;
int *py = &y;
x = 7;
*py = 5;
py = px;
*px = *px + y + *py;
printf(“%d %d\n”, *px, *py);
What prints?
Pop QuizPop Quiz
int x, y;
int *px = &x;
int *py = &y;
x = 7;
*py = 5;
py = px;
*px = *px + y + *py;
printf(“%d %d\n”, *px, *py);
19 19
Hilarious ImplicationsHilarious Implications
• Remember we only have “in” parameters in C• So we can fake it!• Let’s say we want to write a function (procedure) to
swap two numbers:void swap(int a, int b)
{
int t;
t = a;
a = b;
b = t;
}
• Doesn’t work since parameters are “in”– Pass by Value
But we can fool the computer!But we can fool the computer!
void swap(int *a, int *b)
{
int t;
t = *a;
*a = *b;
*b = t;
}
Called like this:
int x, y;
x = 3;
y = 4;
swap(&x, &y);
Notice 1. We didn’t actuallycreate any pointer variablesin our calling sequence.
2. We don’t change a and b inside of swap just what they are pointing to...
Notice 1. We didn’t actuallycreate any pointer variablesin our calling sequence.
2. We don’t change a and b inside of swap just what they are pointing to...
Pop QuizPop Quiz
#include <stdio.h>
void print_num (int* x)
{
printf("Number: %d\n", *x);
}
int main (void)
{
int a = 3;
int* b;
b = &a;
print_num(??);
return 0;
}
Which one goes here to print 3?
b*b&b
Which one goes here to print 3?
b*b&b
Pop AnswerPop Answer
#include <stdio.h>
void print_num (int* x)
{
printf("Number: %d\n", *x);
}
int main (void)
{
int a = 3;
int* b;
b = &a;
print_num(b);
return 0;
}
Pop QuizPop Quiz
#include <stdio.h>
void print_num (int* x)
{
printf("Number: %d\n", *x);
}
int main (void)
{
int a = 3;
int* b;
b = &a;
print_num(b);
return 0;
}
b Pointer to an int*b What b is pointing at&b Address where b is stored
b Pointer to an int*b What b is pointing at&b Address where b is stored
Now it gets...Now it gets...
• C allows us to have arrays which appear to be like other languages
int a[100];• creates an array of 100 elements which can be
referenced as a[0] through a[99].• Note that an array created in this manner is truly an
array• However, we can also do strange and wonderful
things now like:
int *b;
b = a;• Note: This is the same as b = &a[0];
Strange and Wonderful Thing IStrange and Wonderful Thing I
int main(void) {
int a[10];
int *b;
int i;
for (i = 0; i < 10; i++)
a[i] = i;
b = a; /* What happens here, recall b = &a[0] */
for (i=0; i < 10; i++)
{
*(b+i) = *(b+i) * 2; /* And here? */
printf("%d %d\n", i, a[i]);
}
return 0;
}
Strange and Wonderful Thing IIStrange and Wonderful Thing II
int main(void) {
int a[10];
int *b;
int i;
for (i = 0; i < 10; i++)
a[i] = i;
b = a;
for (i=0; i < 10; i++)
{
b[i] = b[i] * 2; /* Say what (kareoke)? */
printf("%d %d\n", i, a[i]);
}
return 0;
}
Strange and Wonderful Thing IIIStrange and Wonderful Thing III
int main(void) {
int a[10];
int *b;
int i;
for (i = 0; i < 10; i++)
a[i] = i;
b = a;
for (i=0; i < 10; i++)
{
i[b] = i[b] * 2; /* Aarrrgggghhhhhhhhh!!! */
printf("%d %d\n", i, a[i]);
}
return 0;
}
b[4]
4[b]
CautionCaution
• Many people will say that arrays in C are just pointer manipulations but an actual array is a special thing
• So while it was okay to say
b = a• It would have been wrong to say
a = b
• Once you create a true array:
int a[10];• You shouldn’t try and assign something else to “a”
““Actual Array”Actual Array”
• In C, we can dynamically allocate memory and we’re going to just show you enough to make you incredibly dangerous.
• DON’T CUT GREENLEE’S LECTURES ON THIS SUBJECT
• It could be a huge mistake!
• We are only telling you part of the story!!!!!!!!!!!!!!!!!
Allocating MemoryAllocating Memory
• There is a function in a C library which allows you to ask for some memory. You tell it how much. It tells you thata. You got it and where it’s located
OR
b. You didn’t get it
• The feared and dreaded
void *malloc(size_t n)
PseudomemoriesPseudomemories
• Remember the newnew function in Pseudocode?
• You said: current <- new(Node)current <- new(Node)
• So the idea was that the size of the Node was looked up somewhere and then enough memory was allocated to hold one Node.
• Malloc works sort of like that only you can ask for as much memory as you want.
• Note that both return pointers.
Warning, Danger, Will RobinsonWarning, Danger, Will Robinson
• This is not a complete treatment of dynamic memory management in C.
• There is no automatic garbage collection in C• There is no automatic garbage collection in C• There is no automatic garbage collection in C• There is no automatic garbage collection in C• You must eventually learn
– Memory allocation– Memory reallocation– Memory deallocation
• From Mr. Greenlee - You’ll love it, honest! ;-)
Simple MallocSimple Malloc
• Let’s say you want space for 100 ints.• Here is what you do:
int *pintpint = (int *)malloc(100 * sizeof(int));if (null == pint){
/* You did not get the space! */ /* Handle error here -- very important */
}/* Now you have effectively an array of ints */for (i = 0; i < 100; i++){
pint[i] = 0;}
Going crazy?Going crazy?
• Did we mention pointers to pointers?• We did this before:
int x;
int *px;
px = &x• We can also go one (or more) step(s) further:
int **ppx;
ppx = &px;• Which would allow us to do things like:
**ppx = 42; /* Puts 42 into x */
Ready to run back to Java yet?
VisuallyVisually
ADDR CONT SYMB
1000 ?? x
2000 1000 px
3000 ?? ppx
int x;
int *px;
int **ppx;
px = &x;
VisuallyVisually
ADDR CONT SYMB
1000 ?? x
2000 1000 px
3000 2000 ppx
int x;
int *px;
int **ppx;
px = &x;
ppx = &px;
VisuallyVisually
ADDR CONT SYMB
1000 42 x
2000 1000 px
3000 2000 ppx
int x;
int *px;
int **ppx;
px = &x
ppx = &px;
**ppx = 42;
Stringing You AlongStringing You Along
• Since we’re talking about arrays and pointers and pointers to pointers we should briefly mention strings
• Strings in C are implemented as arrays of characters
• So just as you can say:
int a[ ] = {0, 1, 3, 5}• and C will correctly dimension a to be a[4]
• You can also say:
char b[ ] = {‘t’, ‘e’, ‘s’, ‘t’, ‘\0’}• And you can even say:
char c[ ] = “test”;
Watch this closelyWatch this closely
char aLine[ ] = “Hi, there!”;
char *pLine = “Hi, there!”;• These are similar but not the same!!!• The first actually creates space for an array of
characters (11) which can be subsequently modified
aLine[4] = ‘T’;• The second creates a pointer which is pointing to a
string constant so that
pLine[4] = ‘T’; would be undefined while
pLine = aLine;
pLine[4] = ‘T’; /* is okay */
Over the top!Over the top!
• It is not only possible to have pointers to pointers but one can even use arrays of pointers!
• char *name[ ] = {“Illegal”, “Jan”, ”Feb”, ”Mar”, ”Apr”, ”May”, “Jun”, “Jul”, “Aug”, “Sep”, “Oct”, “Nov”, “Dec”};
• Now for example name[2] is a pointer to the character string ‘F’, ‘e’, ‘b’, ‘\0’
• What would we do with an array of pointers?
ImagineImagine
• We have some names like– Smith, David– Leahy, Bill– Dagon, David– Morales IV, Ricky Martin
• Suppose we want to sort the names but we note that they are of different lengths.
• Instead of running a sort algorithm which swaps the character strings around why not create an array of pointers
We have an array of pointersWe have an array of pointers
Leahy, Bill
Smith, David
Dagon, David
Morales IV, Ricky Martin
name[0]
name[1]
name[3]
name[2]
And we just move the pointers in the And we just move the pointers in the array to sortarray to sort
Leahy, Bill
Smith, David
Dagon, David
Morales IV, Ricky Martin
name[0]
name[1]
name[3]
name[2]
More funMore fun
• If we define
char *names[30];
we get
• The following are all legal:
char z;
names[4] = &z;
names[5] = “fred”;
names[6] = (char*)malloc(20*sizeof(char));
...
names 01
29
Pointersto chars
Running with the big dogsRunning with the big dogs
• The classic data structure in C which is equivalent to– Records in Pseudocode (Pascal)– Classes (without methods) in Java– Whatever in Scheme (Like a list sort of...)
• is called a struct• They look like this
struct ordPair
{
int x;
int y;
};
More structsMore structs• So we could declare
struct ordPair opAlpha, opBeta;• and access them like this
opAlpha.x = 7;
opAlpha.y = 8;
opBeta = opAlpha;• Structs are what we would use for the classic linked
list node
struct LLnode
{
int data
struct LLNode *next;
};
Putting it all togetherPutting it all together
• Here is how we could declare a head pointer:
struct LLnode *head;
• here is how we could get a new node dynamically
head = (struct LLnode *)malloc(sizeof(struct LLnode));
One last thingOne last thing
• C allows you to make up your own type identifiers using typedef
• This is used as follows with struct definitions
typedef struct Node
{
int data
struct Node *next;
} Node;
• Now we can say
Node *head
PreprocessingPreprocessingCompilation begins by moving the C source files through a preprocessor--a simple text substitution device.
One can designate strings for substitution with the expression:
#define <expression> <substitute>#define <expression> <substitute>
#include <stdio.h>#define GREETING “Hello World”
int main ( void ) {
printf (GREETING);
}
int main ( void ) {
printf (“Hello World”);
}
The C preprocessor has many features--and pitfalls.
#define g(y) get_index(y)g(z)
#define g (y) get_index (y)g(z)
A Tale of Two ExpansionsA Tale of Two Expansions
get_index(z)
(y) get_index (y) (z)
Notice the extrawhite space
This is knownas “macro substitution”
The Power of ParensThe Power of Parens
#define DIVIDE(x, y) x/y
DIVIDE(3, 3+4) 3/3+4
#define DIVIDE(x, y) (x)/(y)
DIVIDE (3, 3+4) (3)/(3+4)
Inputs Results
More SubstitutionMore Substitution
#define square(x) x * x#define square(x) x * x
What’s wrong with this?
It could be called thus:
square (z + 4)square (z + 4)
Resulting:
z + 4 * z + 4z + 4 * z + 4
And not:
(z+4) * (z+4)(z+4) * (z+4)
Common Sense PreprocessingCommon Sense Preprocessing
11 Watch extra white space, as shown in the previous examples.
22 Liberally use parentheses to protect order of precedence