Download presentation
Presentation is loading. Please wait.
Published byDaniella Andrews Modified over 8 years ago
1
Topics This Section More C basics Strings Functions Structures Memory
2
Simple Example #include void main(void) { printf(“Hello World. \n \t and you ! \n ”); /* print out a message */ return; } $Hello World. and you ! $
3
Summarizing the Example #include = include header file stdio.h No semicolon at end Small letters only – C is case-sensitive void main(void){ … } is the only code executed printf(“ /* message you want printed */ ”); \n = newline \t = tab Dessert: \ in front of other special characters within printf. printf(“Have you heard of \”The Rock\” ? \n”);
4
Type conversion #include void main(void) { int i,j = 12; /* i not initialized, only j */ float f1,f2 = 1.2; i = (int) f2; /* explicit: i <- 1, 0.2 lost */ f1 = i; /* implicit: f1 <- 1.0 */ f1 = f2 + (int) j; /* explicit: f1 <- 1.2 + 12.0 */ f1 = f2 + j; /* implicit: f1 <- 1.2 + 12.0 */ } Explicit conversion rules for arithmetic operation x=y+z; convert y or z as double <- float <- int <- char, short then type cast it to x ’s type Moral: stick with explicit conversions - no confusion !
5
Strings
6
Review of strings Sequence of zero or more characters, terminated by NUL (literally, the integer value 0 ) NUL terminates a string, but isn’t part of it important for strlen() – length doesn’t include the NUL Strings are accessed through pointers/array names #include at program start
7
String literals Evaluating ″ dog ″ results in memory allocated for three characters ′ d ′, ′ o ′, ′ g ′, plus terminating NUL char *m = ″ dog ″ ; Note: If m is an array name, subtle difference: char m[10] = ″ dog ″ ;
8
String literals Evaluating ″ dog ″ results in memory allocated for three characters ′ d ′, ′ o ′, ′ g ′, plus terminating NUL char *m = ″ dog ″ ; Note: If m is an array name, subtle difference: char m[10] = ″ dog ″ ; 10 bytes are allocated for this array
9
String literals Evaluating ″ dog ″ results in memory allocated for three characters ′ d ′, ′ o ′, ′ g ′, plus terminating NUL char *m = ″ dog ″ ; Note: If m is an array name, subtle difference: char m[10] = ″ dog ″ ; 10 bytes are allocated for this array This is not a string literal; It’s an array initializer in disguise! Equivalent to { ′ d ′, ′ o ′, ′ g ′, ′ \0 ′ }
10
String manipulation functions Read some “source” string(s), possibly write to some “destination” location char *strcpy(char *dst, char const *src); char *strcat (char *dst, char const *src); Programmer’s responsibility to ensure that: destination region large enough to hold result source, destination regions don’t overlap “undefined” behavior in this case – according to C spec, anything could happen! char m[10] = ″ dog ″ ; strcpy(m+1, m);
11
String manipulation functions Read some “source” string(s), possibly write to some “destination” location char *strcpy(char *dst, char const *src); char *strcat (char *dst, char const *src); Programmer’s responsibility to ensure that: destination region large enough to hold result source, destination regions don’t overlap “undefined” behavior in this case – according to C spec, anything could happen! char m[10] = ″ dog ″ ; strcpy(m+1, m); Assuming that the implementation of strcpy starts copying left-to-right without checking for the presence of a terminating NUL first, what will happen?
12
strlen() and size_t size_t strlen(char const *string); /* returns length of string */ size_t is an unsigned integer type, used to define sizes of strings and (other) memory blocks Reasonable to think of “size” as unsigned”... But beware! Expressions involving strlen() may be unsigned (perhaps unexpectedly) if (strlen(x) – strlen(y) >= 0)... avoid by casting: ((int) (strlen(x) – strlen(y)) >= 0) Problem: what if x or y is a very large string? a better alternative: (strlen(x) >= strlen(y))
13
strlen() and size_t size_t strlen(char const *string); /* returns length of string */ size_t is an unsigned integer type, used to define sizes of strings and (other) memory blocks Reasonable to think of “size” as unsigned”... But beware! Expressions involving strlen() may be unsigned (perhaps unexpectedly) if (strlen(x) – strlen(y) >= 0)... avoid by casting: ((int) (strlen(x)) – strlen(y) >= 0) Problem: what if x or y is a very large string? a better alternative: (strlen(x) >= strlen(y)) always true!
14
strcmp() “string comparison” int strcmp(char const *s1, char const *s2); returns a value less than zero if s1 precedes s2 in lexicographical order; returns zero if s1 and s2 are equal; returns a value greater than zero if s1 follows s2. Source of a common mistake: seems reasonable to assume that strcmp returns “true” (nonzero) if s1 and s2 are equal; “false” (zero) otherwise In fact, exactly the opposite is the case!
15
Restricted vs. unrestricted string functions Restricted versions: require an extra integer argument that bounds the operation char *strncpy(char *dst, char const *src, size_t len); char *strncat(char *dst, char const *src, size_t len); int strncmp(char const *s1, char const *s2, size_t len); “safer” in that they avoid problems with missing NUL terminators safety concern with strncpy : If bound isn’t large enough, terminating NUL won’t be written Safe alternative: strncpy(buffer, name, BSIZE); buffer[BSIZE-1] = ′ \0 ′ ;
16
String searching char *strstr(const char *haystack, const char *needle); /* return a pointer to first occurrence of the substring needle in the string haystack. or NULL if the substring is not found */
17
Functions
18
Functions – basic example #include int sum(int a, int b); /* function prototype at start of file */ void main(void){ int total = sum(4,5); /* call to the function */ printf(“The sum of 4 and 5 is %d”, total); } int sum(int a, int b){ /* the function itself - arguments passed by value*/ return (a+b); /* return by value */ }
19
Argument Passing
20
What’s wrong with this ? #include void dosomething(int *ptr); main() { int *p; dosomething(p) printf(“%d”, *p); /* will this work ? */ } void dosomething(int *ptr){ /* passed and returned by reference */ int temp=32+12; ptr = &(temp); } /* compiles correctly, but gives run-time error */
21
Passing and returning arrays #include void init_array(int array[], int size) ; void main(void) { int list[5]; init_array(list, 5); for (i = 0; i < 5; i++) printf(“next:%d”, array[i]); } void init_array(int array[], int size) { /* why size ? */ /* arrays ALWAYS passed by reference */ int i; for (i = 0; i < size; i++) array[i] = 0; }
22
Structures
23
#include struct birthday{ int month; int day; int year; }; main() { struct birthday mybday;/* - no ‘new’ needed ! */ /* then, it’s just like Java ! */ mybday.day=1; mybday.month=1; mybday.year=1977; printf(“I was born on %d/%d/%d”, birth.day, birth.month, birth.year); } Structures Equivalent of Java’s classes with only data (no methods)
24
More on Structures struct person{ char name[41]; int age; float height; struct { /* embedded structure */ int month; int day; int year; } birth; }; struct person me; me.birth.year=1977;……… struct person class[60]; /* array of info about everyone in class */ class[0].name=“Gun”; class[0].birth.year=1971;……
25
Passing/Returning a structure /* pass struct by value */ void display_year_1(struct birthday mybday) { printf(“I was born in %d\n”, mybday.year); }/* - inefficient: why ? */.. /* pass struct by reference */ void display_year_2(struct birthday *pmybday) { printf(“I was born in %d\n”, pmybday->year); /* warning ! ‘->’, not ‘.’, after a struct pointer*/ }.. /* return struct by value */ struct birthday get_bday(void){ struct birthday newbday; newbday.year=1971; /* ‘.’ after a struct */ return newbday; }/* - also inefficient: why ? */
26
typedef int Employees; Employees my_company; /* same as int my_company; */ typedef struct person Person; Person me; /* same as struct person me; */ typedef struct person *Personptr; Personptr ptrtome; /* same as struct person *ptrtome;*/ Synonym for a data type Easier to remember Clean code
27
int month[12]; /* month is a pointer to base address 430*/ month[3] = 7; /* month address + 3 * int elements => int at address (430+3*4) is now 7 */ ptr = month + 2; /* ptr points to month[2], => ptr is now (430+2 * int elements)= 438 */ ptr[5] = 12; /* ptr address + 5 int elements => int at address (434+5*4) is now 12. Thus, month[7] is now 12 */ ptr++; /* ptr <- 438 + 1 * size of int = 442 */ (ptr + 4)[2] = 12; /* accessing ptr[6] i.e., array[9] */ More pointers Now, month[6], *(month+6), (month+4)[2], ptr[3], *(ptr+3) are all the same integer variable.
28
Memory Layout How is memory organized? Text=code, constant data
29
Memory Layout How is memory organized? Text=code, constant data Data = initialized global and static variables
30
Memory Layout How is memory organized? Text=code, constant data Data = initialized global and static variables BSS = (Block Started by Symbol)
31
Memory Layout How is memory organized? Text=code, constant data Data = initialized global and static variables BSS = (Block Started by Symbol) Heap = dynamic memory
32
Memory Layout How is memory organized? Text=code, constant data Data = initialized global and static variables BSS = (Block Started by Symbol) Heap = dynamic memory Stack = local variables
33
Memory Layout
34
Overview of memory management 34 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()
35
Memory Allocation How is memory allocated? Global and static variables = program startup
36
Memory Allocation How is memory allocated? Global and static variables = program startup Local variables = function call
37
Memory Allocation How is memory allocated? Global and static variables = program startup Local variables = function call Dynamic memory = malloc()
38
Memory Allocation
39
Heap-allocated memory This is used for persistent data, that must survive beyond the lifetime of a function call 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!
40
Allocating new heap memory void *malloc(size_t size); Allocate a block of size bytes, return a pointer to the block ( NULL if unable to allocate block) Note: void * denotes a generic pointer type
41
Memory deallocation How is memory deallocated? Global and static variables = program finish
42
Memory deallocation How is memory deallocated? Global and static variables = program finish Local variables = function return
43
Memory deallocation How is memory deallocated? Global and static variables = program finish Local variables = function return Dynamic memory = free()
44
Memory deallocation How is memory deallocated? Global and static variables = program finish Local variables = function return Dynamic memory = free() All memory is deallocated at program termination
45
Memory deallocation How is memory deallocated? Global and static variables = program finish Local variables = function return Dynamic memory = free() All memory is deallocated at program termination It is good style to free allocated memory anyway
46
Memory deallocation
47
Deallocating heap memory void 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!
48
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...
49
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
50
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 */ }
51
Using memory that you don’t own Null pointer 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 ?
52
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); }
53
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 */ }
54
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(); }
55
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++; }
56
Faulty heap management Freeing non-heap memory Freeing unallocated memory void 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 */ }
57
Dynamic Memory
68
Before you go…. Always initialize anything before using it (especially pointers) Don’t use pointers after freeing them Don’t return a function’s local variables by reference No exceptions – so check for errors everywhere An array is also a pointer, but its value is immutable. Many things I haven’t told you – you should be comfortable enough now to read them up by yourself.
69
Dynamic Memory Code Execution: … start with dog(); Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); }
70
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); }
71
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my cat”
72
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my cat” z = 12
73
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my cat” z = 12 *x i = 12 cat() Stack Frame dog() Stack Frame
74
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my cat” z = 12 *x i = 12 r = 4 cat() Stack Frame dog() Stack Frame Static Memory
75
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my hat” z = 12 *x i = 12 r = 4 cat() Stack Frame dog() Stack Frame Static Memory
76
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my hat” z = 12 *x i = 12 r = 4 cat() Stack Frame dog() Stack Frame Static Memory *result 20 bytes Heap Memory
77
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my hat” z = 12 *x i = 12 r = 4 cat() Stack Frame dog() Stack Frame Static Memory *result “my hat x 12” Heap Memory
78
Dynamic Memory Code Execution: Memory: char *cat(char *x, int i) { static int r = 4; x[3] = 'h'; char *result = (char *)malloc(20); sprintf(result, "%s x %d", x, i); return result; } void dog() { char *s = "my cat"; int z = 12; cat(s, z); } *s “my hat” z = 12 r = 4 dog() Stack Frame Static Memory “my hat x 12” Heap Memory
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.