programming structures and dynamic allocation. dynamic memory allocation the memory requirement of...

54
Programming Structures and Dynamic Allocation

Post on 22-Dec-2015

227 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Programming

Structures andDynamic Allocation

Page 2: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Dynamic Memory Allocation

The memory requirement of our program is not always known in advanceArrays have fixed size determined at compile

time We would like to allocate at runtime

Page 3: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

The Memory

Two Parts:1. Stack

Memory is allocated when entering a function Deallocation when the function terminates

2. Heap Programmer control allocation and deallocation

Page 4: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Memory Management

stdlib.h Two operations for memory management

1. Allocation void* malloc(…);

2. Deallocation void free(…);

Page 5: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

The malloc Function

void* malloc(unsigned int nBytes);

malloc is used to dynamically allocate nBytes in memory

malloc returns a pointer to the allocated area on success, NULL on failure

You should always check whether memory was successfully allocated

Remember to #include <stdlib.h>

Page 6: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

The free Function

void free(void *ptr);

Use free(p) to deallocate memory pointed by p

If p doesn’t point to an area allocated by malloc an error occursNo partial deallocation

Always remember to free the allocated memory once you are done with it

Page 7: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Exampleint main(void){ int i, n, *p;

printf("How many numbers will you enter?\n"); scanf("%d", &n);

/* Allocate an int array of the proper size */ p = (int*)malloc(n * sizeof(int)); if (p == NULL) { printf("Memory allocation failed!\n"); return 1; }

...

/* Free the allocated space */ free(p);

return 0;}

Page 8: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Why Casting?

The casting in p = (int *)malloc(n*sizeof(int));

is needed because malloc returns void* :void* malloc(unsigned int nbytes);

The type (void*) specifies a general pointer, which can be cast to any pointer type.

Page 9: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

What is ‘sizeof’ ?

The sizeof operator gets a variable or a type as an input and return its size in bytes

sizeof always calculates the size of the type double x;s1 = sizeof(x); /* s1 is 8 */s2 = sizeof(int) /* s2 is 4 */

Page 10: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Example

char name[25];char* address = (char*)malloc(25);int i;

printf("sizeof(name) = %d\n", sizeof(name));

printf("sizeof(address) = %d\n", sizeof(address));

if (sizeof(&i) == sizeof(address))

printf("True\n");

else

printf("False\n");

254

True

Page 11: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Returning Allocated Memory

Since allocated memory is not deallocated upon function termination we can return its address.

Duplicate a stringchar* strdup(const char* str){ char* dup = (char*)malloc((strlen(str)+1) * sizeof(char)); if (dup != NULL) { strcpy(dup, str); } return dup;}

Page 12: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Exercise

Implement the functionchar* my_strcat(const char *s1, const char *s2); Output – a pointer to a dynamically allocated

concatenation of s1 and s2 For example: The concatenation of “hello_” and

“world!” is the string “hello_world!”

Test your function

Page 13: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Solutionchar* my_strcat(const char *s1, const char *s2){ int len; char *result = NULL;

len = strlen(s1) + strlen(s2) + 1;

result = (char*)malloc(len * sizeof(char)); if (result == NULL) { printf(“Memory allocation failed!\n"); return NULL; }

strcpy(result, s1); strcat(result, s2);

return result;}

Page 14: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

What’s Wrong Here?

char* my_strcat(const char *s1, const char *s2){ int len; char result[500]; /* assume this is enough */

strcpy(result, s1); strcpy(result + strlen(s1), s2);

return result;}

Page 15: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Pitfalls

Accessing un-initialized pointer

int* p;*p = 3;

Using de-allocated memory

int* p = (int*)malloc(SIZE * sizeof(int));... /* do something with p*/free(p);*p = 0;

Page 16: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Structures

Not much in the real world comes to us as simple data types. (e.g. Car, Book, Bank account)

We want to be able to manipulate logical entities as a whole

The individual pieces of the data may exist in one of the basic forms

How do you keep track of what pieces of the data belong together?

Page 17: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Examples

BookTitle, Authors, ISBN, Publisher

Bank AccountOwners, Balance, Credit

CarMake, Model, Year

Page 18: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

A convenient way of grouping several pieces of related information together.

A collection of variables under a single name.

Structures - User Defined Types

Page 19: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Structures - Example

struct point{ double x; double y;};

struct rectangle{ struct point low_left; struct point up_right;};

struct student{ char id[10]; char* name; int avg_grade;};

struct point{ double x, y;};

Page 20: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Defining a struct

struct struct-name{

type field-name1; type field-name2; type field-name3;

...};

Page 21: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Example - Complex Numbers

Structure declaration

Variable definition Define variables of type complex

struct complex { double real, img;};

struct complex c1, c2;

Page 22: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Field Access

Use the . (dot) operator to access a field in a structure

<variable name>.<field name>

If comp is of type complex then to access the real part we write

comp.realand to access the imaginary part we write

comp.img

Page 23: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Example

Printing a complex number

printf("%g + %gi", comp.real, comp.img);

Input from the user

scanf("%lf", &comp.real);

Page 24: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Typdef

Introduce synonyms for typestypedef int Boolean;typedef char* String;

Boolean b;String str = "Text";

Page 25: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Typdef and Structs

Instead of writing struct complex everywhere we can create a shorter synonym using typedef. typdef struct complex Complex

Then use it Complex c1, c2;

Page 26: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

We can combine the typdef with the structure declaration:

typedef struct complex { int real; int img; } Complex;

This is the common way to define new types

Typedef Even Shorter

Page 27: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Structures and Functions

Function can receive structures as their parameters and return structures as their return value

Parameter passing is done by value copy

Similar to basic types

Page 28: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Structures and Functions - Example

Complex make_complex(double real, double img){ Complex temp;

temp.real = real; temp.img = img;

return temp;}

Complex add_complex(Complex c1, Complex c2){ return make_comlex(c1.real + c2.real, c1.img + c2.img);}

Page 29: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf("result = %g+%gi\n", sum.real, sum.img);

return 0;}

… …

real

img

a

… …

real

img

b

… …

real

img

sum

Page 30: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf("result = %g+%gi\n", sum.real, sum.img);

return 0;}

… …

real

img

a

… …

real

img

b

… …

real

img

sum

Page 31: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf("result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

… …

real

img

b

… …

real

img

sum

Page 32: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf("result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

… …

real

img

b

… …

real

img

sum

Page 33: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf("result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

3.2 4.5

real

img

b

… …

real

img

sum

Page 34: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf("result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

3.2 4.5

real

img

b

… …

real

img

sum

Page 35: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

Complex add_complex(Complex x, Complex y){ Complex sum;

sum.real = x.real + y.real; sum.img = x.img + y.img;

return sum;}

1.0 2.0

real

img

x

3.2 4.5

real

img

y

… …

real

img

sum

Page 36: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

Complex add_complex(Complex x, Complex y){ Complex sum;

sum.real = x.real + y.real; sum.img = x.img + y.img;

return sum;}

1.0 2.0

real

img

x

3.2 4.5

real

img

y

… 6.5

real

img

sum

Page 37: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

Complex add_complex(Complex x, Complex y){ Complex sum;

sum.real = x.real + y.real; sum.img = x.img + y.img;

return sum;}

1.0 2.0

real

img

x

3.2 4.5

real

img

y

4.2 6.5

real

img

sum

Page 38: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

Complex add_complex(Complex x, Complex y){ Complex sum;

sum.real = x.real + y.real; sum.img = x.img + y.img;

return sum;}

1.0 2.0

real

img

x

3.2 4.5

real

img

y

4.2 6.5

real

img

sum

Page 39: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf(“result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

3.2 4.5

real

img

b

4.2 6.5

real

img

sum

Page 40: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf(“result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

3.2 4.5

real

img

b

4.2 6.5

real

img

sum

Page 41: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

add_complex – step by step

int main(void){ Complex a, b, sum;

printf("…"); scanf("%lf%lf", &(a.real), &(a.img)); printf("…"); scanf("%lf%lf", &(b.real), &(b.img));

sum = add_complex(a, b);

printf(“result = %g+%gi\n", sum.real, sum.img);

return 0;}

1.0 2.0

real

img

a

3.2 4.5

real

img

b

4.2 6.5

real

img

sum

Page 42: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Assignment

Structures can be assigned (copied) using the assignment operator “=” Bitwise copy – copying the content of one

structure’s memory onto another c1 = add_complex(…);

1001001110101010010101010101110101110101

0000000000000000000000000000000000000000

c1 c2

1001001110101010010101010101110101110101

Page 43: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Arrays in Structs

The entire array is part of the structure When passing the struct to a function (by

value) Changing the array field won’t change the

original array

Page 44: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Pointers in Structs

When copying a struct containing a pointer only the pointer is copied (shallow copy)

Not what the pointer points to we should take extra care when

manipulating structures that contain pointers

Page 45: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Comparison

Structures cannot be compared using the equality operator “==” They must be compared member by

member Usually this will be done in a separate

function

is_equal_complex(Complex c1, Complex c2){ return (c1.real == c2.real) && (c1.img == c2.img);}

Page 46: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Exercise

Implement a multiply_complex function:

Complex multiply_complex(Complex x, Complex y);

Note: if x = a + bi and y = c + di then: z = xy = (ac - bd) + (ad + bc)i

Write a program that uses the above function to multiply two complex numbers given by the user

Page 47: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Solution

Complex make_complex(double real, double img){ Complex temp; temp.real = real; temp.img = img;

return temp;}

Complex multiply_complex(Complex a, Complex b){ return make_complex(a.real * b.real - a.img * b.img, a.real * b.img + a.img * b.real);}

Page 48: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Pointers to Structures

Same as with other types Pointer definition

structure-name * variable-name; Complex* comptr;

Complex c, *cptr;cptr = &c;

defines a complex and a pointer to a complex

assign the address of the complex variable to the complex pointer

Page 49: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

To access the fields we can write:

(*pcomp).real(*pcomp).img

Complex comp;Complex *pcomp = &comp;

Accessing Fields Using Pointers

Page 50: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Alternative Syntax

Pointer to structures are extremely common

Alternative notation as a shorthand p→member-of-structure → is minus sign followed by >

Examplepcomp→realpcomp→img

Page 51: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Example

typdef struct point { double x, y;} Point;

typdef struct rect { Point pt1, pt2;} Rect;

Rect r, *rp = &r;

r.pt1.x(*rp).pt1.xrp->pt1.x

equivalent

Page 52: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Example

typedef struct point{ double x; double y;} Point;

typedef struct circle{ Point center; double radius;} Circle;

Page 53: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Example

int is_in_circle(Point *p, Circle *c){ double x_dist, y_dist;

x_dist = p->x - c->center.x; y_dist = p->y - c->center.y;

return (x_dist * x_dist + y_dist * y_dist <= c->radius * c->radius);}

A point is in a circle if its distance from the center is smaller than the radius.

Page 54: Programming Structures and Dynamic Allocation. Dynamic Memory Allocation The memory requirement of our program is not always known in advance  Arrays

Exit

void exit(int status);

Sometimes an error occurs and we want the program to immediately exit (e.g. division by zero, memory allocation failure)

exit terminates the program de-allocates all resources (close open files, free

memory, …) To be used only in extreme situations Remember to #include <stdlib.h>