Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 CSC 211 Data Structures Lecture 6 Dr. Iftikhar Azim Niaz 1.

Similar presentations


Presentation on theme: "1 CSC 211 Data Structures Lecture 6 Dr. Iftikhar Azim Niaz 1."— Presentation transcript:

1 1 CSC 211 Data Structures Lecture 6 Dr. Iftikhar Azim Niaz ianiaz@comsats.edu.pk 1

2 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

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

4 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:

5 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

6 6 Dynamic Memory Allocation Diagram

7 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

8 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()

9 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!

10 10 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) 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

11 11 Allocating new heap memory void *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);

12 12 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!

13 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

14 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

15 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

16 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 */ }

17 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 ?

18 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); }

19 19 Using memory that you don’t own Common error in 64-bit applications:  int s 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, 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

20 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

21 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

22 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 */ }

23 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(); }

24 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++; }

25 25 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 */ }

26 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

27 27 Static Data Allocation 0x000000000xFFFFFFFF address space program code (text) static data heap (dynamically allocated) stack PC SP This is The Heap.

28 28 Allocating Memory in The Heap See 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

29 29 Allocating Memory in The Heap See 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

30 30 Allocating Memory in The Heap See 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()

31 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

32 32 Typical usage of malloc() and free() char *getTextFromSomewhere(…); int main(){ char * txt; …; txt = getTextFromSomewhere(…); …; printf("The text returned is %s.", txt); free(txt); }

33 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()

34 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

35 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

36 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!

37 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

38 38 Operator new Syntax new 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.

39 39 Operator new char* ptr; ptr = new char; *ptr = ‘B’; cout << *ptr; NOTE: Dynamic data has no variable name 2000 ??? ???ptr 5000 5000 ‘B’

40 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 }

41 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.

42 42 Operator delete char* ptr; ptr = new char; *ptr = ‘B’; cout << *ptr; delete ptr; 5000 5000 ‘B’ 2000 ptr ??? NOTE: delete deallocates the delete deallocates the memory pointed to by ptr memory pointed to by ptr

43 43 Example char *ptr ; ptr = new char[ 5 ]; strcpy( ptr, “Bye” ); ptr[ 0 ] = ‘u’; delete [] ptr; ptr = NULL; ‘B’ ‘y’ ‘e’ ‘\0’ ‘u’ ptr ptr3000??? 6000 6000???NULL // deallocates the array pointed to by ptr // ptr itself is not deallocated // the value of ptr becomes undefined

44 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

45 45 Memory leak example int *ptr1 = new int; int *ptr2 = new int; *ptr1 = 8; *ptr2 = 5; ptr18 5 ptr2 ptr18 5 ptr2 ptr2 = ptr1; How to avoid?

46 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.

47 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.

48 48 Dangling Pointer example int *ptr1 = new int; int *ptr2; *ptr1 = 8; ptr2 = ptr1; ptr18 ptr2 delete ptr1; ptr1 ptr2 How to avoid?

49 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

50 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

51 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.

52 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

53 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

54 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;

55 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

56 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”;

57 57 Accessing Members of Structures Accessing structure members  Dot operator (. ) used with structure variables card myCard; printf( "%s", myCard.suit );  Arrow operator ( -> ) used with pointers to structure variables card *myCardPtr = &myCard; printf( "%s", myCardPtr->suit );  myCardPtr->suit is equivalent to ( *myCardPtr ).suit

58 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

59 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

60 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

61 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.c 2 The card shuffling and dealing program using structures */ 3#include 4#include 5#include 6 7struct card { 8 const char *face; 9 const char *suit; 10}; 11 12typedef struct card Card; 13 14void fillDeck( Card * const, const char *[], 15 const char *[] ); 16void shuffle( Card * const ); 17void deal( const Card * const ); 18 19int 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"}; 29 30 srand( time( NULL ) );

62 2. Randomize 2. fillDeck 2.1 shuffle 2.2 deal 3. Function definitions 31 32 fillDeck( deck, face, suit ); 33 shuffle( deck ); 34 deal( deck ); 35 return 0; 36} 37 38void fillDeck( Card * const wDeck, const char * wFace[], 39 const char * wSuit[] ) 40{ 41 int i; 42 43 for ( i = 0; i <= 51; i++ ) { 44 wDeck[ i ].face = wFace[ i % 13 ]; 45 wDeck[ i ].suit = wSuit[ i / 13 ]; 46 } 47} 48 49void shuffle( Card * const wDeck ) 50{ 51 int i, j; 52 Card temp; 53 54 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.

63 3. Function definitions 61 62void deal( const Card * const wDeck ) 63{ 64 int i; 65 66 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.

64 Program Output Eight of Diamonds Ace of Hearts Eight of Clubs Five of Spades Seven of Hearts Deuce of Diamonds Ace of Clubs Ten of Diamonds Deuce of Spades Six of Diamonds Seven of Spades Deuce of Clubs Jack of Clubs Ten of Spades King of Hearts Jack of Diamonds Three of Hearts Three of Diamonds Three 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 Spades Queen of Diamonds Five of Diamonds Ace of Spades Nine of Hearts King of Clubs Five of Hearts King of Spades Four of Diamonds Queen of Hearts Eight of Hearts Four of Spades Jack of Hearts Four of Clubs Queen of Clubs

65 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)

66 66 Structure declarations Combined variable and type declaration struct 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 */

67 67 Structure declarations struct 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 )

68 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; }

69 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

70 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

71 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 aligned Four bytes wasted for each structure! Memory layout idamountnum_avail cost currency_type

72 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 id amount num_avail cost currency_type

73 73 Structures as function arguments Structures are scalars, so they can be returned and passed as arguments – just like int s, char s 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 const void changestruct(struct BIG const *s);

74 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 struct union Number { int x; float y; }; Union myObject;

75 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

76 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 */

77 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

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

79 1. Define union 1.1 Initialize variables 2. Set variables 3. Print 1/* Fig. 10.5: fig10_05.c 2 An example of a union */ 3#include 4 5union number { 6 int x; 7 double y; 8}; 9 10int 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}

80 Program Output Put a value in the integer member and print both members. int: 100 double: -92559592117433136000000000000000000000000000000000000000000000.00000 Put a value in the floating member and print both members. int: 0 double: 100.000000

81 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'

82 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"

83 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'

84 84 Support for Strings in C Most string manipulation is done through functions in 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

85 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, 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

86 86 Character Handling Library

87 87 String Conversion Functions in C See 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)

88 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!

89 89 C-Style Multidimensional Arrays Most 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. For storage and processing, use a two-dimensional array. Example: A table of test scores for several different students on several different tests.

90 90 Declaring Two-Dimensional Arrays Standard 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]

91 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

92 92 Higher-Dimensional Arrays The 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 4 th semester for student 2 on test 3 // number of semesters, students and tests all counted from zero!!

93 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] [29]

94 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) 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 ) base( scoresTable[10 ]) + 3*( sizeof double ) scoresTable[10][4]...... [3] [0] [0] [1] [1] [9] [9][10]... = 0x12348 + 10 * (4 * 8) + 3 * 8 = 0x124a0 = 0x12348 + 10 * (4 * 8)

95 95 Implementing multidimensional arrays More 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? ABCDABCDEFGHEFGHIJKLIJKLABCDABCDEFGHEFGHIJKLIJKL A character requires a single byte Compiler instructed to reserve 12 consecutive bytes Two ways to store consecutively i.e. rowwise and columnwise.

96 96 Implementing multidimensional arrays ABCDEFGHIJKLABCDEFGHIJKL RowWise A B C D E F G H I J K L ColumnWise A E I B F J C G K D H L ABCDEFGHIJKLABCDEFGHIJKL ABCDEFGHIJKLABCDEFGHIJKL

97 97 Summary Dynamic Memory Management with Pointers  malloc()calloc()free() realloc()  new and delete operators Structures Unions Strings Multidimensional Arrays


Download ppt "1 CSC 211 Data Structures Lecture 6 Dr. Iftikhar Azim Niaz 1."

Similar presentations


Ads by Google