programming structures and dynamic allocation. dynamic memory allocation the memory requirement of...
Post on 22-Dec-2015
227 views
TRANSCRIPT
Programming
Structures andDynamic Allocation
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
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
Memory Management
stdlib.h Two operations for memory management
1. Allocation void* malloc(…);
2. Deallocation void free(…);
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>
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
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;}
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.
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 */
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
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;}
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
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;}
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;}
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;
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?
Examples
BookTitle, Authors, ISBN, Publisher
Bank AccountOwners, Balance, Credit
CarMake, Model, Year
A convenient way of grouping several pieces of related information together.
A collection of variables under a single name.
Structures - User Defined Types
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;};
Defining a struct
struct struct-name{
type field-name1; type field-name2; type field-name3;
...};
Example - Complex Numbers
Structure declaration
Variable definition Define variables of type complex
struct complex { double real, img;};
struct complex c1, c2;
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
Example
Printing a complex number
printf("%g + %gi", comp.real, comp.img);
Input from the user
scanf("%lf", &comp.real);
Typdef
Introduce synonyms for typestypedef int Boolean;typedef char* String;
Boolean b;String str = "Text";
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;
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
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
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);}
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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);}
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
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);}
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
To access the fields we can write:
(*pcomp).real(*pcomp).img
Complex comp;Complex *pcomp = ∁
Accessing Fields Using Pointers
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
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
Example
typedef struct point{ double x; double y;} Point;
typedef struct circle{ Point center; double radius;} Circle;
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.
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>