csc 211 data structures lecture 6

97
1 CSC 211 Data Structures Lecture 6 Dr. Iftikhar Azim Niaz [email protected] 1

Upload: linus

Post on 23-Feb-2016

56 views

Category:

Documents


4 download

DESCRIPTION

CSC 211 Data Structures Lecture 6. Dr. Iftikhar Azim Niaz [email protected]. 1. Last Lecture Summary I. Concept of Pointer Pointer operators Address and Indirection Pointer Arithmetic Pointer and functions Pass by Value Pass by Reference Pointer and Arrays. 2. Objectives Overview. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: CSC 211 Data Structures Lecture 6

1

CSC 211Data Structures

Lecture 6

Dr. Iftikhar Azim [email protected]

1

Page 2: CSC 211 Data Structures Lecture 6

2

Last Lecture Summary I Concept of Pointer Pointer operators

Address and Indirection Pointer Arithmetic Pointer and functions

Pass by Value Pass by Reference

Pointer and Arrays

2

Page 3: CSC 211 Data Structures Lecture 6

3

Objectives Overview Dynamic Memory Management with Pointers Structures Unions Strings Multidimensional Arrays

Page 4: CSC 211 Data Structures Lecture 6

4

Dynamic Memory Allocation

Static memory - where global and static variables live

Heap memory - dynamically allocated at execution time- "managed" memory accessed using pointers

Stack memory - used by automatic variables

In C and C++, three types of memory are used by programs:

Page 5: CSC 211 Data Structures Lecture 6

5

3 Kinds of Program Data STATIC DATA: Allocated at compiler time

DYNAMIC DATA: explicitly allocated and deallocated during program execution by C++ instructions written by programmer using operators new and delete

AUTOMATIC DATA: automatically created at function entry, resides in activation frame of the function, and is destroyed when returning from function

Page 6: CSC 211 Data Structures Lecture 6

6

Dynamic Memory Allocation Diagram

s ta tic da ta

S tack

H eap

Run-tim

e allocatedm

emory

Com

pile-time

allocatedm

emory

P rog ramcode

H igh -end

Low -end

Page 7: CSC 211 Data Structures Lecture 6

7

Allocation of Memory Static Allocation: Allocation of memory space at

compile time. Dynamic Allocation: Allocation of memory

space at run time. Dynamic allocation is useful when

arrays need to be created whose extent is not known until run time

complex structures of unknown size and/or shape need to be constructed as the program runs

objects need to be created and the constructor arguments are not known until run time

Page 8: CSC 211 Data Structures Lecture 6

8

Overview of memory management Stack-allocated memory When a function is called, memory is allocated for

all of its parameters and local variables. Each active function call has memory on the stack

(with the current function call on top) When a function call terminates,

the memory is deallocated (“freed up”)

Ex: main() calls f(),f() calls g()g() recursively calls g() main()

f()

g()

g()

Page 9: CSC 211 Data Structures Lecture 6

9

Overview of memory management Heap-allocated memory This is used for persistent data, that must survive

beyond the lifetime of a function call global variables dynamically allocated memory – C statements can create

new heap data (similar to new in Java/C++) Heap memory is allocated in a more complex way

than stack memory Like stack-allocated memory, the underlying system

determines where to get more memory – the programmer doesn’t have to search for free memory space!

Page 10: CSC 211 Data Structures Lecture 6

10

Allocating new heap memoryvoid *malloc(size_t size); Allocate a block of size bytes,

return a pointer to the block(NULL if unable to allocate block)

void *calloc(size_t num_elements, size_t element_size); Allocate a block of num_elements * element_size bytes,

initialize every byte to zero,return pointer to the block(NULL if unable to allocate block)

Note: void * denotes a generic pointer type

Page 11: CSC 211 Data Structures Lecture 6

11

Allocating new heap memoryvoid *realloc(void *ptr, size_t new_size); Given a previously allocated block starting at ptr,

change the block size to new_size, return pointer to resized block

If block size is increased, contents of old block may be copied to a completely different region

In this case, the pointer returned will be different from the ptr argument, and ptr will no longer point to a valid memory region

If ptr is NULL, realloc is identical to malloc

Note: may need to cast return value of malloc/calloc/realloc:

char *p = (char *) malloc(BUFFER_SIZE);

Page 12: CSC 211 Data Structures Lecture 6

12

Deallocating heap memoryvoid free(void *pointer); Given a pointer to previously allocated memory,

put the region back in the heap of unallocated memory Note: easy to forget to free memory when no

longer needed... especially if you’re used to a language with “garbage

collection” like Java This is the source of the notorious “memory leak”

problem Difficult to trace – the program will run fine for some

time, until suddenly there is no more memory!

Page 13: CSC 211 Data Structures Lecture 6

13

Checking for successful allocation Call to malloc might fail to allocate memory, if

there’s not enough available Easy to forget this check, annoying to have to do it

every time malloc is called...

solution:#define mallocDON’T CALL malloc DIRECTLY!#define MALLOC(num,type) (type *)alloc((num)*sizeof(type))extern void *alloc(size_t size);

Garbage inserted into source code if programmer uses malloc

Use MALLOC instead...Scales memory region appropriately

(Note use of parameters in #define)Also, calls “safe” alloc function

Page 14: CSC 211 Data Structures Lecture 6

14

Checking for successful allocation implementation of alloc:

#undef malloc

void *alloc(size_t size) { void *new_mem; new_mem = malloc(size); if (new_mem == NULL) exit(1); return new_mem;} Nice solution – as long as “terminate the

program” is always the right response

Page 15: CSC 211 Data Structures Lecture 6

15

Memory errors Using memory that you have not initialized

Using memory that you do not own

Using more memory than you have allocated

Using faulty heap memory management

Page 16: CSC 211 Data Structures Lecture 6

16

Using memory that you have not initialized Uninitialized memory read Uninitialized memory copy

not necessarily critical – unless a memory read follows

void foo(int *pi) {int j;*pi = j;/* UMC: j is uninitialized, copied into *pi */

}void bar() {

int i=10;foo(&i);printf("i = %d\n", i);/* UMR: Using i, which is now junk value */

}

Page 17: CSC 211 Data Structures Lecture 6

17

Using memory that you don’t own Null pointer read/write

Zero page read/write

typedef struct node {struct node* next;int val;

} Node;

int findLastNodeValue(Node* head) {while (head->next != NULL) { /* Expect NPR */head = head->next;}return head->val; /* Expect ZPR */

}

What if head is NULL?

Page 18: CSC 211 Data Structures Lecture 6

18

Using memory that you don’t own Invalid pointer read/write

Pointer to memory that hasn’t been allocated to program

void genIPR() {int *ipr = (int *) malloc(4 * sizeof(int));int i, j;i = *(ipr - 1000); j = *(ipr + 1000); /* Expect IPR */free(ipr);

}

void genIPW() {int *ipw = (int *) malloc(5 * sizeof(int));*(ipw - 1000) = 0; *(ipw + 1000) = 0; /* Expect IPW */free(ipw);

}

Page 19: CSC 211 Data Structures Lecture 6

19

Using memory that you don’t own Common error in 64-bit applications: ints are 4 bytes but pointers are 8 bytes If prototype of malloc() not provided, return value will

be cast to a 4-byte int

/*Forgot to #include <malloc.h>, <stdlib.h> in a 64-bit application*/void illegalPointer() {

int *pi = (int*) malloc(4 * sizeof(int));pi[0] = 10; /* Expect IPW */printf("Array value = %d\n", pi[0]); /* Expect IPR */

}

Four bytes will be lopped off this value – resulting in an invalid pointer value

Page 20: CSC 211 Data Structures Lecture 6

20

Using memory that you don’t own Free memory read/write Access of memory that has been freed earlier

int* init_array(int *ptr, int new_size) {ptr = (int*) realloc(ptr, new_size*sizeof(int));memset(ptr, 0, new_size*sizeof(int));return ptr;

}int* fill_fibonacci(int *fib, int size) {

int i;/* oops, forgot: fib = */ init_array(fib, size);/* fib[0] = 0; */ fib[1] = 1;for (i=2; i<size; i++)fib[i] = fib[i-1] + fib[i-2];return fib;

}

What if array is moved to new location?

Remember: realloc may move entire block

Page 21: CSC 211 Data Structures Lecture 6

21

Using memory that you don’t own Beyond stack read/write

char *append(const char* s1, const char *s2) {const int MAXSIZE = 128;char result[128];int i=0, j=0;for (j=0; i<MAXSIZE-1 && j<strlen(s1); i++,j++) {result[i] = s1[j];}for (j=0; i<MAXSIZE-1 && j<strlen(s2); i++,j++) {result[i] = s2[j];}result[++i] = '\0';return result;

}

Function returns pointer to stack memory – won’t be valid after

function returns

result is a local array name –stack memory allocated

Page 22: CSC 211 Data Structures Lecture 6

22

Using memory that you haven’t allocated Array bound read/write

void genABRandABW() {const char *name = “Safety Critical";char *str = (char*) malloc(10);strncpy(str, name, 10);str[11] = '\0'; /* Expect ABW */printf("%s\n", str); /* Expect ABR */

}

Page 23: CSC 211 Data Structures Lecture 6

23

Faulty heap management Memory leak

int *pi;void foo() {

pi = (int*) malloc(8*sizeof(int));/* Allocate memory for pi *//* Oops, leaked the old memory pointed to by pi */…free(pi); /* foo() is done with pi, so free it */

}void main() {

pi = (int*) malloc(4*sizeof(int));/* Expect MLK: foo leaks it */foo();

}

Page 24: CSC 211 Data Structures Lecture 6

24

Faulty heap management Potential memory leak

no pointer to the beginning of a block not necessarily critical – block beginning may still be reachable via

pointer arithmetic

int *plk = NULL;void genPLK() {

plk = (int *) malloc(2 * sizeof(int)); /* Expect PLK as pointer variable is incremented

past beginning of block */plk++;

}

Page 25: CSC 211 Data Structures Lecture 6

25

Faulty heap management Freeing non-heap memory Freeing unallocated memoryvoid genFNH() {

int fnh = 0;free(&fnh); /* Expect FNH: freeing stack memory */

}void genFUM() {

int *fum = (int *) malloc(4 * sizeof(int));free(fum+1); /* Expect FUM: fum+1 points to middle of a block */free(fum);free(fum); /* Expect FUM: freeing already freed memory */

}

Page 26: CSC 211 Data Structures Lecture 6

26

Definition — The Heap A region of memory provided by most operating

systems for allocating storage not in Last in, First out discipline

I.e., not a stack

Must be explicitly allocated and released May be accessed only with pointers

Remember, an array is equivalent to a pointer

Many hazards to the C programmer

Page 27: CSC 211 Data Structures Lecture 6

27

Static Data Allocation

0x00000000

0xFFFFFFFF

address space

program code(text)

static data

heap(dynamically allocated)

stack(dynamically allocated)

PC

SPThis is The Heap.

Page 28: CSC 211 Data Structures Lecture 6

28

Allocating Memory in The Heap See <stdlib.h>void *malloc(size_t size);void free(void *ptr);void *calloc(size_t nmemb, size_t size);void *realloc(void *ptr, size_t size);

malloc() — allocates size bytes of memory from the heap and returns a pointer to it.

NULL pointer if allocation fails for any reason free() — returns the chunk of memory pointed to

by ptr Must have been allocated by malloc or calloc

Page 29: CSC 211 Data Structures Lecture 6

29

Allocating Memory in The Heap See <stdlib.h>void *malloc(size_t size);void free(void *ptr);void *calloc(size_t nmemb, size_t size);void *realloc(void *ptr, size_t size);

malloc() — allocates size bytes of memory from the heap and returns a pointer to it.

NULL pointer if allocation fails for any reason free() — returns the chunk of memory pointed to

by ptr Must have been allocated by malloc or calloc

Segmentation fault and/or big-

time error if bad pointer

Page 30: CSC 211 Data Structures Lecture 6

30

Allocating Memory in The Heap See <stdlib.h>

void *malloc(size_t size);void free(void *ptr);void *calloc(size_t nmemb, size_t size);void *realloc(void *ptr, size_t size);

malloc() — allocates size bytes of memory from the heap and returns a pointer to it.

NULL pointer if allocation fails for any reason free() — returns the chunk of memory pointed to

by ptr Must have been allocated by malloc or calloc

free() knows size

of chunk

allocated by malloc(

) or

calloc()

Page 31: CSC 211 Data Structures Lecture 6

31

Notes calloc() is just a variant of malloc() malloc() is analogous to new in C++ and

Java new in C++ actually calls malloc()

free() is analogous to delete in C++ delete in C++ actually calls free() Java does not have delete — uses garbage collection to

recover memory no longer in use

Page 32: CSC 211 Data Structures Lecture 6

32

Typical usage of malloc() and free()char *getTextFromSomewhere(…);

int main(){char * txt;…;txt = getTextFromSomewhere(…);…;printf("The text returned is %s.", txt);free(txt);

}

Page 33: CSC 211 Data Structures Lecture 6

33

Typical usage of malloc() and free()char * getTextFromSomewhere(…){

char *t;...t = malloc(stringLength);...return t;

}

int main(){char * txt;…;txt = getTextFromSomewhere(…);…;printf("The text returned is %s.", txt);free(txt);

}

getTextFromSomewhere() creates a new string using malloc()

Page 34: CSC 211 Data Structures Lecture 6

34

Typical usage of malloc() and free()char * getTextFromSomewhere(…){

char *t;...t = malloc(stringLength);...return t;

}

int main(){char * txt;…;txt = getTextFromSomewhere(…);…;printf("The text returned is %s.", txt);free(txt);

}

Pointer to text is assigned to

txt in calling function

Page 35: CSC 211 Data Structures Lecture 6

35

Usage of malloc() and free()char *getText(…){

char *t;...t = malloc(stringLength);...return t;

}

int main(){char * txt;…;txt = getText(…);…;printf("The text returned is %s.", txt);free(txt);

}

main() must remember to

free the storage pointed to

by txt

Page 36: CSC 211 Data Structures Lecture 6

36

Definition – Memory Leak The steady loss of available memory due to

forgetting to free() everything that was malloc’ed.

Bug-a-boo of most large C and C++ programs

If you “forget” the value of a pointer to a piece of malloc’ed memory, there is no way to find it again!

Killing the program frees all memory!

Page 37: CSC 211 Data Structures Lecture 6

37

Dynamic Memory Allocation in C++ In C, functions such as malloc() are used to dynamically allocate memory from the Heap.

In C++, this is accomplished using the new and delete operators

new is used to allocate memory during execution time returns a pointer to the address where the object is

to be stored always returns a pointer to the type that follows the

new

Page 38: CSC 211 Data Structures Lecture 6

38

Operator new Syntaxnew DataType

new DataType [IntExpression]

If memory is available, in an area called the heap (or free store) new allocates the requested object or array, and returns a pointer to (address of ) the memory allocated.

Otherwise, program terminates with error message.

The dynamically allocated object exists until the delete operator destroys it.

Page 39: CSC 211 Data Structures Lecture 6

39

Operator new

char* ptr;

ptr = new char;

*ptr = ‘B’;

cout << *ptr;

NOTE: Dynamic data has no variable name

2000

???

ptr

5000

5000‘B’

Page 40: CSC 211 Data Structures Lecture 6

40

The NULL Pointer There is a pointer constant called the “null pointer”

denoted by NULL But NULL is not memory address 0.

NOTE: It is an error to dereference a pointer whose value is NULL. Such an error may cause your program to crash, or behave erratically. It is the programmer’s job to check for this.

while (ptr != NULL) { . . . // ok to use *ptr here }

Page 41: CSC 211 Data Structures Lecture 6

41

Operator delete Syntax delete Pointer

delete [ ] Pointer

The object or array currently pointed to by Pointer is deallocated, and the value of Pointer is undefined. The memory is returned to the free store.

Good idea to set the pointer to the released memory to NULL

Square brackets are used with delete to deallocate a dynamically allocated array.

Page 42: CSC 211 Data Structures Lecture 6

42

Operator delete

char* ptr;

ptr = new char;

*ptr = ‘B’;

cout << *ptr;

delete ptr;

5000

5000‘B’

2000

ptr

???

NOTE: delete deallocates the memory pointed to by ptr

Page 43: CSC 211 Data Structures Lecture 6

43

Example char *ptr ;

ptr = new char[ 5 ];

strcpy( ptr, “Bye” );

ptr[ 0 ] = ‘u’;

delete [] ptr;

ptr = NULL;

‘B’ ‘y’ ‘e’ ‘\0’‘u’

ptr3000

???

6000

6000???NULL

// deallocates the array pointed to by ptr// ptr itself is not deallocated// the value of ptr becomes undefined

Page 44: CSC 211 Data Structures Lecture 6

44

Memory leaks When you dynamically create objects, you can

access them through the pointer which is assigned by the new operator

Reassigning a pointer without deleting the memory it pointed to previously is called a memory leak

It results in loss of available memory space

Page 45: CSC 211 Data Structures Lecture 6

45

Memory leak example

int *ptr1 = new int;int *ptr2 = new int;*ptr1 = 8;*ptr2 = 5;

ptr18

5ptr2

ptr18

5ptr2

ptr2 = ptr1;

How to avoid?

Page 46: CSC 211 Data Structures Lecture 6

46

Inaccessible object An inaccessible object is an unnamed object

that was created by operator new and which a programmer has left without a pointer to it.

It is a logical error and causes memory leaks.

Page 47: CSC 211 Data Structures Lecture 6

47

Dangling Pointer It is a pointer that points to dynamic memory

that has been deallocated. The result of dereferencing a dangling pointer

is unpredictable.

Page 48: CSC 211 Data Structures Lecture 6

48

Dangling Pointer example

int *ptr1 = new int;int *ptr2;*ptr1 = 8;ptr2 = ptr1;

ptr18

ptr2

delete ptr1;

ptr1

ptr2How to avoid?

Page 49: CSC 211 Data Structures Lecture 6

49

Dynamic Arrays You would like to use an array data structure

but you do not know the size of the array at compile time.

You find out when the program executes that you need an integer array of size n=20.

Allocate an array using the new operator:

int* y = new int[20]; // or int* y = new int[n]y[0] = 10;y[1] = 15; // use is the same

Page 50: CSC 211 Data Structures Lecture 6

50

Dynamic Arrays ‘y’ is a lvalue; it is a pointer that holds the

address of 20 consecutive cells in memory. It can be assigned a value. The new operator

returns as address that is stored in y. We can write:

y = &x[0];y = x; // x can appear on the

right// y gets the address of

the// first cell of the x array

Page 51: CSC 211 Data Structures Lecture 6

51

Dynamic Arrays We must free the memory we got using the

new operator once we are done with the y array.

delete[ ] y;

We would not do this to the x array because we did not use new to create it.

Page 52: CSC 211 Data Structures Lecture 6

52

Structures Collections of related variables (aggregates)

under one name Can contain variables of different data types

Commonly used to define records to be stored in files

Combined with pointers, can create linked lists, stacks, queues, and trees

Page 53: CSC 211 Data Structures Lecture 6

53

Structure Definitions Example

struct card { char *face; char *suit;

}; struct introduces the definition for structure

card card is the structure name and is used to

declare variables of the structure type card contains two members of type char *

These members are face and suit

Page 54: CSC 211 Data Structures Lecture 6

54

Structure Definitions struct information

A struct cannot contain an instance of itself Can contain a member that is a pointer to the same

structure type A structure definition does not reserve space in memory

Instead creates a new data type used to declare structure variables

Declarations Declared like other variables:

card oneCard, deck[ 52 ], *cPtr; Can use a comma separated list:

struct card { char *face; char *suit;} oneCard, deck[ 52 ], *cPtr;

Page 55: CSC 211 Data Structures Lecture 6

55

Structure Definitions Valid Operations

Assigning a structure to a structure of the same type Taking the address (&) of a structure Accessing the members of a structure Using the sizeof operator to determine the size of

a structure

Page 56: CSC 211 Data Structures Lecture 6

56

Initializing Structures Initializer lists

Example:card oneCard = { "Three", "Hearts" };

Assignment statements Example:

card threeHearts = oneCard; Could also declare and initialize threeHearts as

follows:card threeHearts;threeHearts.face = “Three”;threeHearts.suit = “Hearts”;

Page 57: CSC 211 Data Structures Lecture 6

57

Accessing Members of Structures Accessing structure members Dot operator (.) used with structure variablescard myCard;printf( "%s", myCard.suit );

Arrow operator (->) used with pointers to structure variablescard *myCardPtr = &myCard;printf( "%s", myCardPtr->suit );

myCardPtr->suit is equivalent to( *myCardPtr ).suit

Page 58: CSC 211 Data Structures Lecture 6

58

Using Structures With Functions Passing structures to functions Pass entire structure

Or, pass individual members Both pass call by value

To pass structures call-by-reference Pass its address Pass reference to it

To pass arrays call-by-value Create a structure with the array as a member Pass the structure

Page 59: CSC 211 Data Structures Lecture 6

59

typedef Creates synonyms (aliases) for previously

defined data types Use typedef to create shorter type names Example:

typedef struct Card *CardPtr; Defines a new type name CardPtr as a

synonym for type struct Card * typedef does not create a new data type

Only creates an alias

Page 60: CSC 211 Data Structures Lecture 6

60

Example using Structures High-Performance Card-shuffling and

Dealing Simulation Pseudocode:

Create an array of card structures Put cards in the deck Shuffle the deck Deal the cards

Page 61: CSC 211 Data Structures Lecture 6

1. Load headers

1.1 Define struct

1.2 Function prototypes

1.3 Initialize deck[] and face[]

1.4 Initialize suit[]

1 /* Fig. 10.3: fig10_03.c2 The card shuffling and dealing program using structures */3 #include <stdio.h>4 #include <stdlib.h>5 #include <time.h>67 struct card { 8 const char *face;9 const char *suit;10 };1112 typedef struct card Card;1314 void fillDeck( Card * const, const char *[], 15 const char *[] );16 void shuffle( Card * const );17 void deal( const Card * const );1819 int main()20 { 21 Card deck[ 52 ];22 const char *face[] = { "Ace", "Deuce", "Three", 23 "Four", "Five",24 "Six", "Seven", "Eight", 25 "Nine", "Ten",26 "Jack", "Queen", "King"};27 const char *suit[] = { "Hearts", "Diamonds", 28 "Clubs", "Spades"};2930 srand( time( NULL ) );

Page 62: CSC 211 Data Structures Lecture 6

2. Randomize

2. fillDeck

2.1 shuffle

2.2 deal

3. Function definitions

3132 fillDeck( deck, face, suit );33 shuffle( deck );34 deal( deck );35 return 0;36 }3738 void fillDeck( Card * const wDeck, const char * wFace[], 39 const char * wSuit[] )40 { 41 int i;4243 for ( i = 0; i <= 51; i++ ) { 44 wDeck[ i ].face = wFace[ i % 13 ];45 wDeck[ i ].suit = wSuit[ i / 13 ];46 }47 }4849 void shuffle( Card * const wDeck )50 { 51 int i, j;52 Card temp;5354 for ( i = 0; i <= 51; i++ ) { 55 j = rand() % 52;56 temp = wDeck[ i ];57 wDeck[ i ] = wDeck[ j ];58 wDeck[ j ] = temp;59 }60 }

Put all 52 cards in the deck. face and suit determined by remainder (modulus).

Select random number between 0 and 51. Swap element i with that element.

Page 63: CSC 211 Data Structures Lecture 6

3. Function definitions

6162 void deal( const Card * const wDeck )63 { 64 int i;6566 for ( i = 0; i <= 51; i++ )67 printf( "%5s of %-8s%c", wDeck[ i ].face, 68 wDeck[ i ].suit,69 ( i + 1 ) % 2 ? '\t' : '\n' );70 }

Cycle through array and print out data.

Page 64: CSC 211 Data Structures Lecture 6

Program OutputEight of Diamonds Ace of HeartsEight of Clubs Five of SpadesSeven of Hearts Deuce of Diamonds Ace of Clubs Ten of DiamondsDeuce of Spades Six of DiamondsSeven of Spades Deuce of Clubs Jack of Clubs Ten of Spades King of Hearts Jack of DiamondsThree of Hearts Three of DiamondsThree of Clubs Nine of Clubs Ten of Hearts Deuce of Hearts Ten of Clubs Seven of Diamonds Six of Clubs Queen of Spades Six of Hearts Three of Spades Nine of Diamonds Ace of Diamonds Jack of Spades Five of Clubs King of Diamonds Seven of Clubs Nine of Spades Four of Hearts Six of Spades Eight of SpadesQueen of Diamonds Five of Diamonds Ace of Spades Nine of Hearts King of Clubs Five of Hearts King of Spades Four of DiamondsQueen of Hearts Eight of Hearts Four of Spades Jack of Hearts Four of Clubs Queen of Clubs

Page 65: CSC 211 Data Structures Lecture 6

65

C structures: aggregate, yet scalar aggregate in that they hold multiple data items at one time named members hold data items of various types like the notion of class/field in C or C++

– but without the data hiding features scalar in that C treats each structure as a unit

as opposed to the “array” approach: a pointer to a collection of members in memory

entire structures (not just pointers to structures) may be passed as function arguments, assigned to variables, etc.

Interestingly, they cannot be compared using ==(rationale: too inefficient)

Page 66: CSC 211 Data Structures Lecture 6

66

Structure declarations Combined variable and type declarationstruct tag {member-list} variable-list; Any one of the three portions can be omitted

struct {int a, b; char *p;} x, y; /* omit tag */ variables x, y declared with members as described:

int members a, b and char pointer p. x and y have same type, but differ from all others –

even if there is another declaration:struct {int a, b; char *p;} z;

/* z has different type from x, y */

Page 67: CSC 211 Data Structures Lecture 6

67

Structure declarationsstruct S {int a, b; char *p;}; /* omit variables */ No variables are declared, but there is now a

type struct S that can be referred to later

struct S z; /* omit members */ Given an earlier declaration of struct S, this

declares a variable of that type

typedef struct {int a, b; char *p;} S; /* omit both tag and variables */

This creates a simple type name S(more convenient than struct S)

Page 68: CSC 211 Data Structures Lecture 6

68

Recursively defined structures Obviously, you can’t have a structure that contains an instance of itself as a member – such a data item would be infinitely large

But within a structure you can refer to structures of the same type, via pointers

struct TREENODE { char *label; struct TREENODE *leftchild, *rightchild;}

Page 69: CSC 211 Data Structures Lecture 6

69

Recursively defined structures When two structures refer to each other, one must be declared in incomplete (prototype) fashion

struct HUMAN;struct PET { char name[NAME_LIMIT]; char species[NAME_LIMIT]; struct HUMAN *owner;} fido = {″Fido″, ″Canis lupus familiaris″};struct HUMAN { char name[NAME_LIMIT]; struct PET pets[PET_LIMIT];} sam = {″Sam″, {fido}};

We can’t initialize the owner member at this point,

since it hasn’t been declared yet

Page 70: CSC 211 Data Structures Lecture 6

70

Direct access operator s.m subscript and dot operators have same precedence and

associate left-to-right, so we don’t need parentheses for sam.pets[0].species

Indirect access s->m: equivalent to (*s).m Dereference a pointer to a structure, then return a

member of that structure Dot operator has higher precedence than indirection

operator , so parentheses are needed in (*s).m(*fido.owner).name or fido.owner->name

Member access

. evaluated first: access owner member* evaluated next: dereference pointer to HUMAN

. and -> have equal precedence and associate left-to-right

Page 71: CSC 211 Data Structures Lecture 6

71

struct COST { int amount; char currency_type[2]; }struct PART { char id[2]; struct COST cost; int num_avail; }layout of struct PART:

Here, the system uses 4-byte alignment of integers,so amount and num_avail must be alignedFour bytes wasted for each structure!

Memory layout

id amount num_avail

cost

currency_type

Page 72: CSC 211 Data Structures Lecture 6

72

A better alternative (from a space perspective):struct COST { int amount; char currency_type; }struct PART { struct COST cost; char id[2]; int num_avail;}

Memory layout

idamount num_avail

cost

currency_type

Page 73: CSC 211 Data Structures Lecture 6

73

Structures as function arguments Structures are scalars, so they can be returned and passed as arguments – just like ints, chars

struct BIG changestruct(struct BIG s); Call by value: temporary copy of structure is created Caution: passing large structures is inefficient

– involves a lot of copying avoid by passing a pointer to the structure

instead:void changestruct(struct BIG *s); What if the struct argument is read-only?

Safe approach: use constvoid changestruct(struct BIG const *s);

Page 74: CSC 211 Data Structures Lecture 6

74

Unions Memory that contains a variety of objects over time Only contains one data member at a time Members of a union share space Conserves storage Only the last data member defined can be accessed union declarations

Same as structunion Number { int x; float y;};Union myObject;

Page 75: CSC 211 Data Structures Lecture 6

75

Unions Storage

size of union is the size of its largest member avoid unions with widely varying member sizes;

for the larger data types, consider using pointers instead

Initialization Union may only be initialized to a value appropriate

for the type of its first member

Page 76: CSC 211 Data Structures Lecture 6

76

Unions Like structures, but every member occupies

the same region of memory! Structures: members are “and”ed together: “name

and species and owner” Unions: members are “xor”ed together

union VALUE { float f; int i; char *s;};/* either a float xor an int xor a string */

Page 77: CSC 211 Data Structures Lecture 6

77

Unions Up to programmer to determine how to

interpret a union (i.e. which member to access) Often used in conjunction with a “type” variable

that indicates how to interpret the union value

enum TYPE { INT, FLOAT, STRING };struct VARIABLE { enum TYPE type; union VALUE value;};

Access type to determine how to interpret value

Page 78: CSC 211 Data Structures Lecture 6

78

Valid Union Operators Assignment to union of same type: = Taking address: & Accessing union members: . Accessing members using pointers: ->

Page 79: CSC 211 Data Structures Lecture 6

1. Define union

1.1 Initialize variables

2. Set variables

3. Print

1 /* Fig. 10.5: fig10_05.c2 An example of a union */3 #include <stdio.h>45 union number { 6 int x;7 double y;8 };910 int main()11 { 12 union number value;13 14 value.x = 100;15 printf( "%s\n%s\n%s%d\n%s%f\n\n",16 "Put a value in the integer member",17 "and print both members.",18 "int: ", value.x, 19 "double:\n", value.y );20 21 value.y = 100.0;22 printf( "%s\n%s\n%s%d\n%s%f\n",23 "Put a value in the floating member",24 "and print both members.",25 "int: ", value.x, 26 "double:\n", value.y );27 return 0;28 }

Page 80: CSC 211 Data Structures Lecture 6

Program Output

Put a value in the integer memberand print both members.int: 100double:-92559592117433136000000000000000000000000000000000000000000000.00000 Put a value in the floating memberand print both members.int: 0double:100.000000

Page 81: CSC 211 Data Structures Lecture 6

81

Strings Arrays of characters End with a null byte ('\0') String literals implicitly provide

the null terminator:"hello" becomes: 'h' 'e' 'l' 'l' 'o' '\0'

Page 82: CSC 211 Data Structures Lecture 6

82

Strings in C Definition:– A string is a character array ending

in '\0' — i.e., char s[256]; char t[] = "This is an initialized string!"; char *u = "This is another string!";

String constants are in double quotes May contain any characters Including \" and \' —

String constants may not span lines However, they may be concatenated — e.g., "Hello, " "World!\n" is the same as "Hello, World!\n"

Page 83: CSC 211 Data Structures Lecture 6

83

Strings in C (continued) Let

char *u = "This is another string!"; Then

u[0] == 'T'u[1] == 'h'u[2] == 'i'…u[21] == 'g'u[22] == '!'u[23] == '\0'

Page 84: CSC 211 Data Structures Lecture 6

84

Support for Strings in C Most string manipulation is done through functions

in <string.h>

String functions depend upon final '\0' So you don’t have to count the characters!

Examples:– int strlen(char *s) – returns length of string

Excluding final '\0' char* strcpy(char *s, char *ct) – Copies string ct to

string s, return s s must be big enough to hold contents of ct ct may be smaller than s

See K&R pp. 105-106 for various implementations

Page 85: CSC 211 Data Structures Lecture 6

85

Support for Strings in C (continued) Examples (continued):– int strcmp(char *s, char *t)

lexically compares s and t, returns <0 if s < t, >0 ifs > t, zero if s and t are identical D&D §8.6, K&R p. 106

char* strcat(char *s, char *ct) Concatenates string ct to onto end of string s, returns s s must be big enough to hold contents of both strings!

Other string functions strchr(), strrchr(), strspn(), strcspn() strpbrk(), strstr(), strtok(), …

K&R pp. 249-250; D&D §8.6

Page 86: CSC 211 Data Structures Lecture 6

86

Character Handling Library <ctype.h>

Prototype Description

int isdigit( int c ) Returns true if c is a digit and false otherwise.

int isalpha( int c ) Returns true if c is a letter and false otherwise. int isalnum( int c ) Returns true if c is a digit or a letter and false otherwise. int isxdigit( int c ) Returns true if c is a hexadecimal digit character and false otherwise. int islower( int c ) Returns true if c is a lowercase letter and false otherwise. int isupper( int c ) Returns true if c is an uppercase letter; false otherwise. int tolower( int c ) If c is an uppercase letter, tolower returns c as a lowercase letter. Otherwise, tolower

returns the argument unchanged. int toupper( int c ) If c is a lowercase letter, toupper returns c as an uppercase letter. Otherwise, toupper

returns the argument unchanged. int isspace( int c ) Returns true if c is a white-space character—newline ('\n'), space (' '), form feed

('\f'), carriage return ('\r'), horizontal tab ('\t'), or vertical tab ('\v')—and false otherwise

int iscntrl( int c ) Returns true if c is a control character and false otherwise. int ispunct( int c ) Returns true if c is a printing character other than a space, a digit, or a letter and false

otherwise. int isprint( int c ) Returns true value if c is a printing character including space (' ') and false

otherwise. int isgraph( int c ) Returns true if c is a printing character other than space (' ') and false otherwise.

Page 87: CSC 211 Data Structures Lecture 6

87

String Conversion Functions in C See <stdlib.h>

double atof(const char *s)int atoi(const char *s)long atol(const char *s)

double strtod(const char *s, char **endp)long strtol(const char *s, char **endp, int base)

unsigned long strtoul(const char *s, char **endp, int base)

Page 88: CSC 211 Data Structures Lecture 6

88

Dilemma Question:–

If strings are arrays of characters, … and if arrays cannot be returned from functions, …

how can we manipulate variable length strings and pass them around our programs?

Answer:– Use storage allocated in The Heap!

Page 89: CSC 211 Data Structures Lecture 6

89

C-Style Multidimensional ArraysMost high level languages support arrays with more than one

dimension.

2D arrays are useful when data has to be arranged in tabular form.

Higher dimensional arrays appropriate when several characteristics associated with data.

Test 1 Test 2 Test 3 Test 4Student 1 99.0 93.5 89.0 91.0Student 2 66.0 68.0 84.5 82.0Student 3 88.5 78.5 70.0 65.0

: : : : :: : : : :

Student-n 100.0 99.5 100.0 99.0

For storage and processing, use a two-dimensional array.

Example: A table of test scores for several different students on

several different tests.

Page 90: CSC 211 Data Structures Lecture 6

90

Declaring Two-Dimensional ArraysStandard form of declaration:element_type array_name[NUM_ROWS][NUM_COLUMNS];

Example:const int NUM_ROWS = 30,

NUM_COLUMNS = 4;

double scoresTable[NUM_ROWS][NUM_COLUMNS];

Initialization List the initial values in braces, row by row; May use internal braces for each row to improve readability.

Example:double rates[2][3] = {{0.50, 0.55, 0.53}, // first row {0.63, 0.58, 0.55}}; // second row

...

[0][1][2][3]

[29]

[0] [[1] [2] [3]

Page 91: CSC 211 Data Structures Lecture 6

91

Processing Two-Dimensional Arrays

Remember: Rows (and) columns are numbered from zero!!

Use doubly-indexed variables:scoresTable[2][3] is the entry in row 2 and column 3

­ ­ row index column index

Use nested loops to vary the two indices, most often in a rowwise manner.

Counting from 0

Page 92: CSC 211 Data Structures Lecture 6

92

Higher-Dimensional ArraysThe methods for 2D arrays extend in the obvious way to 3D arrays.

Example: To store and process a table of test scores for several different students on several different tests for several different semesters

const int SEMS = 10, STUDENTS = 30, TESTS = 4;typedef double ThreeDimArray[SEMS][STUDENTS][TESTS];ThreeDimArray gradeBook;

gradeBook[4][2][3] is the score of 4th semester for student 2 on test 3

// number of semesters, students and tests all counted from zero!!

Page 93: CSC 211 Data Structures Lecture 6

93

Arrays of Arrays

double scoresTable[30][4];

Declares scoresTable to be a one-dimensional array containing 30 elements, each of which is a one-dimensional array of 4 real numbers; that is, scoresTable is a one-dimensional array of rows , each of which has 4 real values. We could declare it as

typedef double RowOfTable[4];

RowOfTable scoresTable[30];

...

[0][1][2][3]

[29]

[0] [[1] [2] [3]

...

[0] [[1] [2] [3][0][1][2][3]

[29]

Page 94: CSC 211 Data Structures Lecture 6

94

scoresTable[i] is the i-th row of the table

Address Translation:The array-of-arrays structure of multidimensional arrays explains address translation. Suppose the base address of scoresTable is 0x12348:

scoresTable[10] 0x12348 + 10*(sizeof RowOfTable)

In general, an n-dimensional array can be viewed (recursively) as a one-dimensional array whose elements are (n - 1)-dimensional arrays.

In any case:

scoresTable[i][j] should be thought of as (scoresTable[i])[j] that is, as finding the j-th element of scoresTable[i].

®

scoresTable[10][3] ® base(scoresTable[10]) + 3*(sizeof double)

scoresTable[10][4]

...

...[3]

[0] [1]

[9][10]

...

= 0x12348 + 10 * (4 * 8) + 3 * 8 = 0x124a0

= 0x12348 + 10 * (4 * 8)

Page 95: CSC 211 Data Structures Lecture 6

95

Implementing multidimensional arraysMore complicated than one dimensional arrays.

Memory is organized as a sequence of memory locations, and is thus 1D

How to use a 1D structure to store a MD structure?A B C DE F G HI J K L

A character requires a single byte

Compiler instructed to reserve 12 consecutive bytes

Two ways to store consecutively i.e. rowwise and columnwise.

Page 96: CSC 211 Data Structures Lecture 6

96

Implementing multidimensional arraysA B C DE F G HI J K L

RowWiseABCDEFGHIJKL

ColumnWiseAEIBFJCGKDHL

A B C DE F G HI J K L

A B C DE F G HI J K L

Page 97: CSC 211 Data Structures Lecture 6

97

Summary Dynamic Memory Management with Pointers

malloc() calloc() free() realloc() new and delete operators

Structures Unions Strings Multidimensional Arrays