S09: Structures Required: PM: Ch 11.1,4, pgs 205-226 PM: Ch 11.5, pgs 227-229 Recommended: K&R, Chapter 6 Pointer Tutorial (Chps 5,9) CS 224 Chapter Project Homework L01: Warm-up L02: FSM HW01 HW02 L03: Blinky L04: Microarch L05b: Traffic Light L06a: Morse Code HW03 HW04 HW05 HW06 L07b: Morse II L08a: Life L09a: Pong HW07 HW08 HW09 HW10 S00: Introduction Unit 1: Digital Logic S01: Data Types S02: Digital Logic Unit 2: ISA S03: ISA S04: Microarchitecture S05: Stacks / Interrupts S06: Assembly Unit 3: C S07: C Language S08: Pointers S09: Structs S10: I/O BYU CS 124 Pointers and Arrays 2 Learning Objectives… enum typedef’s Structures structs in structs Array of structs struct Pointers Dynamic Memory Allocation Linked List union Bit fields BYU CS 224 Structs 3 enum Enum Enums in C are a way to map identifiers to integral values (thus avoiding magic numbers in your code). The advantage of enum over #define is that it has scope. Two types of enum’s: Only visible within the block it was declared. Easier to change values – let the compiler do the work. Named: enum greekType { ALPHA, BETA, GAMMA }; Unnamed: enum { HOMER, MARGE, BART, LISA }; Values start at zero, unless specified. enum enum enum enum BYU CS 224 { zero, one, two, three }; animals { cat=1, dog, cow=9, sheep, goat }; plants { grass, roses, cabbages, oaktree }; BOOLEAN { FALSE, TRUE }; Structs 4 typedef’s Why typedef? We use variables with logical names - why not use data types with logical names? Most data types are platform dependent! What’s an "int"? 8-bits, 16-bits, 32-bits? What’s a “long”? Better question: why memorize it? typedef’s introduce synonyms for types which could have been declared some other way. typedef’s make your code more portable. typedef’s usually declared in single .h file. Syntax: typedef <type> <name>; BYU CS 224 Structs 5 typedef’s Why typedef? How to use typedef’s: 1) Create a logical data type scheme. 2) Create a “typedef.h” file for each microcontroller platform you use. 3) #include "typedef.h" in each of your files. 4) Use the new data type names. typedef typedef typedef typedef typedef typedef signed char int8; unsigned char uint8; signed short int16; unsigned short uint16; signed long int32; unsigned long uint32; Replace: unsigned char variable; with: uint8 variable; BYU CS 224 Structs 6 Structures Structures A structure is a collection of variables, possibly of different types, grouped together under a single name (tag). Help organize complicated data. Must be defined prior to a structure variable being declared. Definitions include a tag, member elements, and a variable definition. struct flightType { char flightNum[6]; int altitude; int longitude; int latitude; int heading; double airSpeed; }; // // // // // // max 6 characters in meters in tenths of degrees in tenths of degrees in tenths of degrees in km/hr Structure definition does not allocate memory. BYU CS 224 Structs 7 Structures Structures Memory for a struct is allocated when a variable is declared using the new structure definition type: struct flightType plane; Structure members are laid out in the order specified by the definition. Members of an allocated struct can be accessed with the “dot” operator: plane.altitude = 10000; plane.heading = 800; BYU CS 224 plane.flightNum[0] plane.flightNum[1] plane.flightNum[2] plane.flightNum[3] plane.flightNum[4] plane.flightNum[5] plane.altitude plane.longitude plane.latitude plane.heading plane.airspeed Structs 0x0000(SP) 0x0002(SP) 0x0004(SP) 0x0006(SP) 0x0008(SP) 0x000a(SP) 0x000c(SP) 0x000e(SP) 0x0010(SP) 0x0012(SP) 0x0014(SP) 8 Structures Structure Example #include <stdio.h> #include <string.h> Does not allocate memory struct person { char name[32]; long ssn; }; struct person barney, fred; Allocates two global memory structs int main() { strcpy(barney.name, "Rubble, Barney"); barney.ssn = 555234561; strcpy(fred.name, "Flintstone, Fred"); fred.ssn = 123451234; printf(“\n%s %ld", fred.name, fred.ssn); printf(“\n%s %ld", barney.name, barney.ssn); } BYU CS 224 Structs 9 structs in structs Structures in Structures One field of a struct can be another structure struct addressStruct { char street[32]; char city[16]; long zipCode; }; person initials ssn struct person { char initials[4]; long ssn; int height; int weight; struct addressStruct address; } tom; height weight address street city int main() { tom.ssn = 555123456; tom.weight = 150; tom.address.zipCode = 84062; } BYU CS 224 zipCode Structs 10 Array of structs Arrays of Structures struct's are data types and hence an array of struct's makes sense: typedef struct flightType { char flightNum[6]; int altitude; int longitude; int latitude; int heading; double airSpeed; } Flight planes[100]; // max 6 characters // in meters // in tenths of degrees // in tenths of degrees // in tenths of degrees // in km/hr Each array element is a structure. To access a member of a particular element in the array, used array index and the “.” dot operator: planes[34].altitude = 10000; BYU CS 224 Structs 11 struct Pointers Pointers and Structures As a data type, pointer variables can point to structures struct person { char name[32]; long ssn; } barney, *rubble; How Much Memory? int main() Not Common { rubble = &barney; strcpy((*rubble).name, “Rubble, Barney”); (*rubble).ssn = 555234561; printf(“%s %ld\n”, (*rubble).name, (*rubble).ssn); } More Common strcpy(rubble->name, “Rubble, Barney”); rubble->ssn = 555234561; printf(“%s %ld\n”, rubble->name, rubble->ssn); BYU CS 224 Structs 12 struct Pointers Pointers and Structures Since pointers can point to structures, then it’s easy to make links between structures. struct person { char initials[2]; long ssn; int height; struct person *father; struct person *mother; }; tom father mother bill susan /* Declare variables and initialize them at the same time */ struct person tom = { "tj", 555235512, 74, NULL, NULL }; struct person bill = { "wj", 351003232, 75, NULL, NULL }; struct person susan = { "sd", 980332153, 70, NULL, NULL }; int main() { /* Set tom's parents pointers */ tom.father = &bill; tom.mother = &susan; printf(“\nTom's mother's height is: %d in", tom.mother->height); } BYU CS 224 Structs tom is a struct and mother is a field in that struct, thus tom.mother is correct. mother is a pointer to a struct and thus mother>height is correct. Combine them for tom.mother->height 13 Dynamic Memory Allocation Memory Usage + Heaps Variable memory is allocated in three areas: Global data section Run-time stack Dynamically allocated - heap SFR’s Global Data Section Heap SP 0x0600 Global variables are allocated in the global data section and are accessible after declaration. Local variables are allocated during execution on the stack. Dynamically allocated variables are allocated memory at run-time from the heap. 0x0000 0x0100 Run-time stack 0x8000 PC Program (Flash) malloc() – allocates memory free() – frees memory 0xffff BYU CS 224 Structs Interrupt Vectors 14 Dynamic Memory Allocation Dynamic Memory Allocation Dynamic memory allocation using malloc() is used for many kinds of programs. When data size is unknown or variable. Building abstract structures like trees and linked lists. The sizeof() function determines how much space is necessary for allocation. int main() { int *dynArray; double *ddynArray; /* Allocate space for 16 ints */ dynArray = (int *)malloc( 16 * sizeof(int) ); dynArray[6] = 65; dynArray[12] = 2; /* Allocate space for 20 doubles */ ddynArray = (double *)malloc( 20 * sizeof(double) ); } BYU CS 224 Structs 15 Dynamic Memory Allocation Dynamic Memory Allocation #include <stdio.h> #include <stdlib.h> A NULL pointer returned from malloc() means it failed and you are likely out of memory. main() { int *dynArray; } /* Allocate space for 16 ints */ dynArray = (int *)malloc( 16 * sizeof(int) ); if (dynArray != NULL) { dynArray[6] = 65; dynArray[12] = 2; Dynamic allocation can be a doSomething( dynArray ); source of bugs in C code. free( dynArray ); Memory leak - allocating memory } and forgetting to free it during program execution. BYU CS 224 Structs 16 Dynamic Memory Allocation Pointers, Structures, & malloc() Common to let malloc() create space for structures struct person { char initials[2]; long ssn; int height; struct person *father; struct person *mother; } *tom, *bill, *susan; int main() { tom = (struct person *)malloc( sizeof( struct person ) ); bill = (struct person *)malloc( sizeof( struct person ) ); susan = (struct person *)malloc( sizeof( struct person ) ); strncpy(tom->initials, "tj“, 2); tom->ssn = 555235512; tom->father = bill; tom->mother = susan; susan->height = 68; /* Since tom is now a pointer, tom->mother->height is correct. */ printf(“\nTom's mother's height is: %d", tom->mother->height); } BYU CS 224 Structs 17 Quiz 9.1 1) 2) 3) 4) 5) 6) How is an int passed to a function? How is a char array passed to a function? How is an auto struct passed to a function? How is a malloc’d struct passed to a function? How many bytes of the heap is removed by a function call to malloc(4)? How many returned? How much memory is allocated for fred? barney? struct person { uint8* name[2]; uint32 ssn; } fred, *barney; BYU CS 224 Structs 18 Linked List Linked List Data Structure A linked list is an collection of nodes, each of which contains data and is connected using pointers. Each node points to the next node in the list. The first node in the list is called the head. The last node in the list is called the tail. list 75 99 NULL Advantages of a linked list 50 Dynamic size. Easy to add/remove nodes. Advantages of an array Easy to quickly access arbitrary elements. BYU CS 224 Structs 19 Linked List Example 9.1 list typedef struct element { int value; struct element* next; } Element; Pattern 50 Factory Element* newElement(int value) { Element* temp; temp = (Element*)malloc( sizeof(Element) ); temp->value = value; temp->next = NULL; return temp; } int main() { /* Create linked list */ Element *list = NULL; list = newElement(50); list->next = newElement(75); list->next->next = newElement(99); printList(list); } BYU CS 224 75 99 NULL void printList(Element* ptr) { while (ptr != NULL) { lcd_printf(" %d", ptr->value); ptr = ptr->next; } lcd_printf("\n"); } Structs 20 Linked List Pre-pend Node // Prepend element to oldList, return ptr to new list ----Element* prepend(Element* element, Element* oldList) { element->next = oldList; return element; // return ptr to new head } // end prepend int main() { Element* myList = newElement(45); myList = prepend(newElement(30), myList); myList = prepend(newElement(10), myList); printList(myList); } myList BYU CS 224 30 10 Structs 45 NULL 21 Linked List Append Node // --- Append element to oldList, return ptr to list --Element* append(Element* element, Element* oldList) { Element* temp = oldList; if (oldList == NULL) return element; // empty list while (temp->next != NULL) temp = temp->next; // find end temp->next = element; return oldList; } // end append int main() { Element* myList = append(newElement(200), myList); myList = append(newElement(201), myList); myList = append(newElement(202), myList); printList(myList); } 201 202 NULL 200 myList BYU CS 224 Structs 22 Linked List Insert Node // Insert element into oldList, return ptr to list ---Element* insert(Element* element, Element* oldList) { Element* temp; if (oldList == NULL) return element; // new list if (element->value < oldList->value) // prepend element { element->next = oldList; return element; } temp = oldList; while ((temp->next != NULL) && (temp->next->value < element->value)) temp = temp->next; element->next = temp->next; temp->next = element; return oldList; } // end insert BYU CS 224 Structs 23 Linked List Insert Node int main() { Element *myList = NULL; RBX430_init(_12MHZ); lcd_init(); lcd_clear(); // init board // init LCD // clear LCD // Insert some items into list myList = insert(newElement(65), myList); myList = insert(newElement(2), myList); myList = insert(newElement(97), myList); myList = insert(newElement(3), myList); myList = insert(newElement(300), myList); printList(myList); } // end main myList BYU CS 224 2 3 65 Structs 97 300 NULL 24 Linked List Free Node Elements in a linked list need to be “freed” or you will have a memory leak. When “freeing” items in a linked list, be careful not to “saw off the limb you’re standing on”. void freeList(Element* list) { if (list == NULL) return; freeList(list->next); free(list); // free end node } int main() { freeList(myList); } BYU CS 224 // free linked list Structs 25 union Union A union is a value that may have any of several representations or formats. Unions are defined like structures (structs), except that each data member begins at the same location in memory. The union object occupies as much space as the largest member. Unions are similar to "variant records" in other languages. union { char c; int i; float f; } x; BYU CS 224 x.c = 'z'; x.i = 5180; x.f = 3.14; Structs c i f 0 1 2 3 26 Bit Fields Bit Fields Specify bit-sized objects within structs or unions. Bit fields do not have addresses—you can't have pointers to them or arrays of them. Be careful using them. Require run-time code to manipulate - could end up using more space than they save. No guarantee of the ordering of fields within machine words, so programs will be non-portable and compiler-dependent. typedef struct { unsigned short hour:5; unsigned short min:6; unsigned short sec:5; } Time time; BYU CS 224 time 15 14 13 12 11 10 hours Structs 9 8 7 6 minutes 5 4 3 2 1 0 seconds 27 Quiz 9.2 1. How many bytes are allocated for mySetting? 2. How do you set hours in mySetting to 12? typedef struct Setting_struct { struct Setting_struct* link; union 15 14 13 12 11 10 9 8 7 { uint16 time; *link struct { uint8 day:3; day hour time uint8 hour:5; high uint8 minute; } times; } date; uint8 high; uint8 low; } Setting mySetting; BYU CS 224 Structs 6 5 4 3 2 1 0 minute low 28 Temperatures Example 9.2 Thermostat temperature entry: typedef unsigned int uint16; typedef unsigned char uint8; enum {SUN=0, MON, TUE, WED, THUR, FRI, SAT}; typedef struct Setting_struct { struct Setting_struct* link; union { uint16 time; // day:hour/minute struct { uint8 day:3; // day of week (0-6) uint8 hour:5; // hour (0-23) uint8 minute; // minute (0-59) } times; } date; uint8 high; uint8 low; } Setting; BYU CS 224 Structs link date high low NULL 29 Temperatures Create New Node // create a new entry Setting* newSetting(uint8 day, uint8 hour, uint8 minute, uint8 high, uint8 low) { // malloc a new node Setting* temp = (Setting*)malloc(sizeof(Setting)); // store entries temp->date.times.day = day; temp->date.times.hour = hour; temp->date.times.minute = minute; temp->high = high; temp->low = low; // null link temp->link = NULL; return temp; } // end newSetting BYU CS 224 Structs 30 Temperatures main int main() { Setting *list = NULL; // Create linked list list = newSetting(MON, 6, 30, 22<<1, 20<<1); list->link = newSetting(WED, 20, 30, 17<<1, 15<<1); list->link->link = newSetting(FRI, 8, 30, 22<<1, 20<<1); list->link->link->link = newSetting(SAT, 18, 30, 20<<1, 18<<1); } 0256 BYU CS 224 025e 1e31 2c 28 0266 1ea3 22 1e Structs 026e 1e45 2c 28 0000 1e96 28 24 31 Temperatures Insert Setting Setting* insertSetting(Setting* setting, Setting* oldList) { Setting* temp = oldList; if (oldList == NULL) return setting; // oldList is empty if (setting->date.time < oldList->date.time) { setting->link = oldList; // pre-pend setting return setting; } while (temp->link != NULL) // Search for location { if (temp->date.time == setting->date.time) { temp->high = setting->high; // replace setting temp->low = setting->low; free(setting); return oldList; } if (temp->link->date.time > setting->date.time) break; temp = temp->link; // next } setting->link = temp->link; // insert setting temp->link = setting; return oldList; } // end insertSetting BYU CS 224 Structs 32 Temperatures Print Setting const char* days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; void printList(Setting* ptr) { while (ptr != NULL) { lcd_printf("\n%s %02d:%02d %4.1f-%4.1f", days[ptr->date.times.day], ptr->date.times.hour, ptr->date.times.minute, (float)ptr->high / 2.0, (float)ptr->low / 2.0 ); ptr = ptr->link; } lcd_printf("\n"); } // end printList BYU CS 224 Structs 33 Temperatures Final Test void main(void) { Setting *list = NULL; RBX430_init(_1MHZ); lcd_init(); lcd_clear(0); // init board // init LCD // Create linked list list = newSetting(MON, 6, 30, 22<<1, 20<<1); list->link = newSetting(WED, 20, 30, 17<<1, 15<<1); list->link->link = newSetting(FRI, 8, 30, 22<<1, 20<<1); list->link->link->link = newSetting(SAT, 18, 30, 20<<1, 18<<1); // Insert some items into list list = insertSetting(newSetting(MON, list = insertSetting(newSetting(SUN, list = insertSetting(newSetting(TUE, list = insertSetting(newSetting(MON, list = insertSetting(newSetting(SAT, } 6, 30, 24<<1, 18<<1), list); 6, 30, 22<<1, 20<<1), list); 6, 30, 22<<1, 20<<1), list); 6, 30, 20<<1, 10<<1), list); 20, 30, 22<<1, 20<<1), list); printList(list); return; BYU CS 224 Structs 34 BYU CS 224 Structs 35