240 likes | 272 Views
Department of Computer and Information Science, School of Science, IUPUI. CSCI 230. Structures. Dale Roberts, Lecturer Computer Science, IUPUI E-mail: droberts@cs.iupui.edu. Introduction. Structures
E N D
Department of Computer and Information Science,School of Science, IUPUI CSCI 230 Structures Dale Roberts, Lecturer Computer Science, IUPUI E-mail: droberts@cs.iupui.edu
Introduction • Structures • A collection of one or more variables, possibly of different types, grouped together under a single name for continent handling. • Commonly used to define records to be stored in files • Combined with pointers, can create linked lists, stacks, queues, and trees 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
Structure Definitions Example: A date consists of several parts, such as the day, month, and year, and the day of the year, and the month name struct date { int day; int month; int year; int year_date; char month_name[4]; }; • date: the name of the structure, called structure tag. • day, month, …: the elements or variables mentioned in a structure are called members. • 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
struct date { • .. .. .. • }; • struct date d1, d2, d3, d4, d5; struct date { .. .. .. } d1, d2, d3; struct date d4, d5; struct { .. .. .. } d1, d2, d3, d4, d5; Declaration of Variables of Structure • Declarations method 1: declared like other variables: declare tag first, and then declare variable. struct card { char *face; char *suit; }; struct card oneCard, deck[ 52 ], *cPtr; method 2: A list of variables can be declared after the right brace and use comma separated list: struct card { char *face; char *suit; } oneCard, deck[ 52 ], *cPtr; method 3: Declare only variables. struct { char *face; char *suit; } oneCard, deck[ 52 ], *cPtr;
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 • Initialization of Structures • Initializer lists Example: struct card oneCard = { "Three", "Hearts" }; Example: struct date d1 = {4, 7, 1776, 186, “Jul”}; struct date d2 = {4, 7, 1776, 186, {‘J’,’u’,’l’,’\0’}}; • Assignment statements Example: card threeHearts = oneCard;
Accessing Members of Structures • Accessing structure members • Dot (.) is a member operator used with structure variables • Syntax: structure_name. member struct card myCard; printf( "%s", myCard.suit ); • One could also declare and initialize threeHearts as follows: struct card threeHearts; threeHearts.face = “Three”; threeHearts.suit = “Hearts”; • Arrow operator (->) used with pointers to structure variables struct card *myCardPtr = &myCard; printf( "%s", myCardPtr->suit ); • myCardPtr->suit is equivalent to (*myCardPtr).suit
Structures • Structure can be nested struct date { int day; int month; int year; int year_date; char month_name[4]; }; struct person { char name [NAME_LEN]; char address[ADDR_LEN}; long zipcode; long ss__number; double salary; struct date birthday; }; struct person emp; emp.birthday.month = 6; emp.birthday.year = 1776; • Name Rule • Members in different structure can have the same name, since they are at different position. • struct s1 { • .. .. .. .. • char name[10]; • .. .. .. .. • } d1; • struct s2 { • .. .. .. .. • int name; • .. .. .. .. } d2; • struct s3 { • .. .. .. .. • int name; struct s3 t3; /* name */ • .. .. .. .. • } d2; • float name;
0 integer 1 2 - 10 9 character 11 (hole) 12 integer 13 0 - 3 integer 4 - 12 9 character 13 - 15 (hole) 16-19 integer Memory Layout Example: struct data1 { int day1; char month[9]; int year; }; • Word (2 bytes) alignment machine – begins (aligns) at even address, such as PC, SUN workstation day1 int 2 bytes month char array 9 bytes (hole) 1 bytes year int 2 bytes • Quad (4 bytes) address alignment – begins (aligns) at quad address, such as VAX 8200 day1 int 4 bytes month char array 9 bytes (hole) 3 bytes year int 4 bytes • You must take care of hole, if you want to access data from very low level (i.e. low-level I/O, byte operations, etc.)
5 bytes 1 byte (hole) 2 bytes 1 byte 1 byte (hole) t1 992 997 998 1000 1001 t2 1002 5 bytes 1 byte (hole) 2 bytes 1 byte 1 byte (hole) sizeof Operator sizeof(struct tag) struct test { char name[5]; int i; /* assume int is 2 bytes */ char s; } t1, t2; main() { printf(“sizeof(struct test) = %d\n”, sizeof (struct test)); printf(“address of t1 = %d\n”, &t1); printf(“address of t2 = %d\n”, &t2); printf(“address of t1.name = %d\n”, t1.name); printf(“address of t1.i = %d\n”, &t1.i); printf(“address of t1.s = %d\n”, &t1.s); } output: sizeof(struct test) = 10 address of t1 = 992 address of t2 = 1002 address of t1.name = 992 address of t1.i = 998 address of t1.s = 1000
Using Structures With Functions • Passing structures to functions • Pass entire structure or pass individual members • Both pass call by value • It is not a good idea to pass a structure to or return from function.The better way is passing a pointer to the structure to the functions and returning a pointer from function. • 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
Using Structures With Functions (cont.) Example: day_of_year(struct date *pd) { int i, day, leap; day = pd -> day; leap = pd->year%4 ==0 && pd->year %100 ==0 || pd->year%400 ==0; for (i=1; i<pd -> month; i++) day += day_tab[leap][i]; return (day); } • The declaration struct date *pd; says that pd is a pointer to a structure of the type date • If p is a pointer to a structure, then p-> member_of_structure refers to the particular members, like pd -> year • p-> member_of_structure is equivalent to (*p).member_of_structure • Notice:‘.’has higher precedence than‘*’; *pd.year is wrong, since pd.year is not a pointer. • Both->and . associate from left to right. So p -> q -> member are (p->q)->member. Example: emp.birthday.month are (emp.birthday).month
Using Structures With Functions (cont.) • -> and . both are at the highest precedence (together with ()for function and [] for array subscripts) Example: struct { int *x; int *y; } *p; ++p->x; is equivalent to ++(p->x) /* increment x, not p */ (++p)->x; /* increment p before access x */ *p->y; /* fetch whatever y points to */ *p->y++; /* increments y after accessing whatever y point to */ (*p->y)++; /* increments whatever y point to, just like *p->y++ */ *p++->y; /* increments p after accessing whatever y point to */
struct card { constchar *face; constchar *suit; }; typedefstruct card Card; void fillDeck( Card * const, constchar *[], constchar *[] ); int main() { Card deck[ 52 ]; constchar *face[] = {"Ace", "Deuce", "Three", "Four", "Five", "Six", Seven", "Eight", “Nine", "Ten", "Jack", "Queen", "King"}; constchar *suit[] = { "Hearts", "Diamonds", "Clubs", "Spades"}; .. .. fillDeck( deck, face, suit ); .. .. } void fillDeck(Card * const wDeck, constchar * wFace[], constchar * wSuit[]) { .. .. } typedef • 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 while it only creates an alias Example:
Unions • union • 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 Number value; • Valid union operations • Assignment to union of same type: = • Taking address: & • Accessing union members: . • Accessing members using pointers: ->
1 /* Fig. 10.5: fig10_05.c 2 An example of a union */ 3 #include <stdio.h> 4 5 union number { 6 int x; 7 double y; 8 }; 9 10 int 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 } Define union Initialize variables Set variables Print 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
Array of Structures Example: (before) char name[PERSON][NAMESIZE]; int tscore[PERSON] int math[PERSON] int english[PERSON] • Initialization of structure array struct person_data{ .. .. .. .. } person[]={ {“Jane”,180,89,91}, {“John”,190,90,100}, .. .. .. .. }; /* similar to 2D array */ Example: using separated arrays average (int tscore, int math, int eng, int n) { int i, total=0,mathtotal = 0, engtotal=0; for (i=0; i<n, i++) { total += *tscore++; mathtotal += *math++; engtotal += *eng++; } • struct person_data{ • char name[NAMESIZE]; • int tscore; • int math; • int english; • } person[PERSON]; (now) the inner brace is not necessary “Jane”,180,89,91, “John”,190,90,100, .. .. .. .. • Example: using pointer to structure • average (struct person_data *person, int n) • { • int i, total=0,mathtotal = 0, engtotal=0; • for (i=0; i<n, i++) { • total += person->tscore; • mathtotal += person->math; • engtotal += person->eng; • person++; • }
Self-Reference Structure • Dynamic Data Structure • Data Structure: link list, tree, graph, … Example: Binary Tree Struct treeNode { char word[SIZE]; int count; struct treeNode *left; struct treeNode *right; /* or struct treeNode *left, *right; */ }; /* Inorder traversal */ tree_print(struct treeNode *p) { if (p!=NULL){ tree_print(p->left); printf(“.. ..”, p->word, .. ..); tree_print(p-> right); } }
Link list Example: Struct listNode { char word[SIZE]; int count; struct listNode *next; }; /* Inorder traversal */ list_print(struct listNode *p) { while (p!=NULL) { printf(“.. ..”, p->word, .. ..); p = p->next; } }
Bit Fields • Bit field • Member of a structure whose size (in bits) has been specified • Enable better memory utilization • Must be declared as int or unsigned • Cannot access individual bits • Declaring bit fields • Follow unsigned or int member with a colon (:) and an integer constant representing the width of the field Example: struct BitCard { unsigned face : 4; unsigned suit : 2; unsigned color : 1; }; • Unnamed bit field • Field used as padding in the structure • Nothing may be stored in the bits • Unnamed bit field with zero width aligns next bit field to a new storage unit boundary struct Example { unsigned a : 13; unsigned : 3; unsigned b : 4; }
Enumeration Constants • Enumeration • Set of integer constants represented by identifiers • Enumeration constants are like symbolic constants whose values are automatically set • Values start at 0 and are incremented by 1 • Values can be set explicitly with = • Need unique constant names Example: enum Months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}; • Creates a new type enum Months in which the identifiers are set to the integers 1 to 12 • Enumeration variables can only assume their enumeration constant values (not the integer representations)
1 /* Fig. 10.18: fig10_18.c 2 Using an enumeration type */ 3 #include <stdio.h> 4 5 enum months { JAN = 1, FEB, MAR, APR, MAY, JUN, 6 JUL, AUG, SEP, OCT, NOV, DEC }; 7 8 int main() 9 { 10 enum months month; 11 constchar *monthName[] = { "", "January", "February", 12 "March", "April", "May", 13 "June", "July", "August", 14 "September", "October", 15 "November", "December" }; 16 17 for ( month = JAN; month <= DEC; month++ ) 18 printf( "%2d%11s\n", month, monthName[ month ] ); 19 20 return 0; 21 } 1 January 2 February 3 March 4 April 5 May 6 June 7 July 8 August 9 September 10 October 11 November 12 December
Storage Management • C supports 4 functions, malloc(), calloc(),free(), and cfree() for storage management • malloc(n): • allocate a node while its content is still ‘garbage’ • n is an integer, indicating the size of memory in byte which you would like to allocate • malloc() return a character pointer to that memory • So, you have to use cast operator (type), to change the type of the pointer. Example: int *ip; ip = (int*) malloc(sizeof(int)); struct treeNode *tp; tp = (struct tnode *) malloc(sizeof(struct tnode));
Storage Management (cont.) • free(p): • free() will release the memory allocated by malloc(). • p is the pointer containing the address returning from malloc(). Example: int *ip; ip = (int*) malloc(sizeof(int)); ... .. .. free(ip); /* Question: can you free(ip) after ip++ ? */ Example: struct treeNode *tp; tp=(struct treeNode *)malloc(sizeof(struct treeNode )); ... .. .. free(tp); • When there is no further memory, malloc() will return NULL pointer. It is a good idea to check the returning value of malloc(). if ((ip=(int *)malloc(sizeof(int))) == NULL){ printf(“\nMemory is FULL\n”); exit(1); } • When you free the memory, you must be sure that you pass the original address returning from malloc() to function free(). Otherwise, system exception may be happened
Storage Management (cont.) • calloc(n,size): • calloc() allow you to allocate an n elements array of same data type. Because n can be an integer variable, you can use calloc() to allocate a dynamic size array. • n is the element number of array that you want to allocate. • size is the number of byte of each element. • Unlike malloc(), calloc() guarantees that memory contents are all zero Example: allocate an array of 10 elements int *ip; ip = (int*) calloc(10, sizeof(int)); *(ip+1) refer to the 2nd element, the same as ip[1] *(ip+i) refer to the i+1th element, the same as ip[i] • Like malloc(), calloc() will return NULL, if no further memory is available. • cfree(p): • cfree() releases the memory allocated by calloc(). Example: cfree(ip);