Programming Structures, enums and unions
Summary } Structures } Declaration } Member access } Function arguments } Memory layout } Array of structures } Typedef } Enums } Unions 2
Idea! } I want to describe a box. I need variables for the width, length, and height } I can use three variables, but wouldn t it be better if I had a single variable to describe a box? Box width length height } That variable can have three parts, the width, length, and height 3
C Structures: Short Introduction } A struct (short for structure) in C is a grouping of variables together into a single type struct nameofstruct type member; type member; }; Note the semicolon at the end! To declare a variable: struct nameofstruct variable_name; 4
C Structures Provide Data Aggregation } Aggregate since they hold multiple data items at one time } Holds data items of various types: named members } 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. } Note that they cannot be compared using == 5
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: } integer members a, b and char pointer p } x and y have same type, but differ from all others: } Even if there is another declaration like this: struct int a, b; char *p;} z; /* z has different type from x, y */ 6
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 later used 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; /* omits both tag and variables */ } This creates a simple type name S } More convenient than struct S 7
Examples #include <stdio.h> struct Box int width; int length; int height; }; struct Circle double radius; }; int main() struct Box b; struct Circle c; } Data structure definition You can declare variables Box width length height Circle radius 8
Recursively Defined Structures } Within a structure you can refer to structures of the same type, via pointers struct TREENODE char *label; struct TREENODE *leftchild, *rightchild; } } Naturally, a structure cannot contain an instance of itself as a member 9
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 was not declared yet 10
Member Access } Direct access operator s.m } Subscript ([]) and dot (.) operators have same precedence and associate left-to-right } Parentheses for sam.pets[0].species are not needed } 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. evaluated first: access owner member * evaluated next: dereference pointer to HUMAN. and -> have equal precedence and associate left-to-right 11
Member Access: Example #include <stdio.h> struct Box int width; int length; int height; }; int main() struct Box b; A period. is used to get to the elements of a struct If x is a struct, x.width is an element in a struct. You can use mixed data types within the struct (int, float, char []) } b.width = 10; b.length = 30; b.height = 10; You can assign values to each member 12
Pointers to Structures: Example } To access the members of a struct it must be used: }. for a variable of the struct s type } -> for a pointer to a struct Box b; /* A variable of type Box */ Box *c; /* A pointer to a Box */ double w; b.width = 5; b.height = 7; b.length = 3; c = &b; /* Same as before */ w = c->width; 13
More Examples struct bankrecordstruct char name[50]; float balance; }; Access values in a struct using a period:. int main() struct BankRecord newacc; /* create new bank record */ printf( Enter account name: ); scanf( %50s, newacc.name); printf( Enter account balance: ); scanf( %d, &newacc.balance); printf( My balance is: %f\n, newacc.balance); } float bal = newacc.balance; 14
Copy via = } You can set two struct type variables equal to each other and each element will be copied int main() struct Box b, c; b.width = 5; b.length = 1; b.height = 2; c = b; // copies all elements of b to c } printf( %d %d %d\n, c.width, c.length, c.height); 15
Nested Structures } If structure is nested, multiple. are required struct point int x; int y; }; struct rectangle struct point tl; /* top left */ struct point br; /* bot right */ }; struct rectangle rect; int tlx=rect.tl.x; /*nested*/ int tly=rect.tl.y; 16
Structures as Function Arguments } Structures are scalars, so they can be returned and passed as arguments just like ints, chars 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); 17
Passing Structures to a Function } Example: passing a struct to a function } All the elements are copied } If an element is a pointer, the pointer is copied but not what it points to! #include <stdio.h> struct card int face; }; void passbyreference(card *c) c->face = 4; } int main(void) Card c; c.face = 1 ; Card *cptr = &c ; // pointer to Card c passbyreference(cptr); #include <stdio.h> struct card int face; }; void passbyvalue(card c) c->face = 4; } int main(void) Card c ; c.face = 1 ; Card *cptr = &c ; // pointer to Card c passbyvalue(*cptr); // no change in c } return EXIT_SUCCESS; } return EXIT_SUCCESS;
Typedef } typedef allows to give a name to a custom type } typedef type newname; } Some typedef examples: } typedef int dollars; } typedef unsigned char Byte; } typedef char Names[40]; // special syntax for vectors } typedef double Mat4x4[4][4]; // and arrays } Then it is possible to declare variables as: } dollars d; // same as } Byte b, c; // same as } Mat4x4 mat; // same as double mat[4][4]; 19
Using Structs with Typedef typedef struct [NameOfStruct] type member; type member; } TypeName; } NameOfStruct is optional } To declare a variable it is only needed to: } TypeName variable_name; 20
Array of Structs } You can declare an array of a structure and manipulate each element typedef struct double radius; int x; int y; char name[10]; } Circle; Circle circles[5]; 21
Size of a Structure: SizeOf typedef struct double radius; /* 8 bytes */ int x; /* 4 bytes */ int y; /* 4 bytes */ char name[10]; /* 10 bytes */ } Circle; printf( Size of Circle struct is %d\n, sizeof(circle)); } But sizeof() reports 28 bytes!!! } Most machines require alignment on 4-byte boundary (a word) 22
Memory Layout struct COST int amount; char currency_type[2]; } struct PART char id[2]; struct COST cost; int num_avail; } layout of struct PART: currency_type id amount num_avail cost Here, the system uses 4-byte alignment of integers, so amount and num_avail must be aligned Four bytes wasted for each structure! 23
Memory Layout 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; } currency_type amount cost id num_avail 24
Complex Types: Review } Structures (user-defined combinations of other types) } Enumerations } Unions (same data, multiple interpretations) } Function pointers } Arrays and Pointers of the above 25
Enumerations } Basically integers } Can use in expressions like ints } Makes code easier to read } Cannot get string equivalence } Carefully using increment/decrement operators if values are not contiguous 26
Enums enum days mon, tue, wed, thu, fri, sat, sun}; // Same as: // #define mon 0 // #define tue 1 //... // #define sun 6 enum days mon=3, tue=8, wed, thu, fri, sat, sun}; // Same as: // #define mon 3 // #define tue 8 //... // #define sun 13 enum days day; // Same as: int day; for(day = mon; day <= sun; day++) if (day == sun) printf("sun\n"); } else printf("day = %d\n", day); } } 27
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 */ 28
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 29
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 30
Unions: Example #include <stdio.h> #include <string.h> union Data int i; float f; char str[20]; }; int main() union Data data; data.i = 10; data.f = 220.5; strcpy( data.str, "C Programming"); printf( "data.i : %d\n", data.i); printf( "data.f : %f\n", data.f); printf( "data.str : %s\n", data.str); } return 0; 31
To Review } Marques de Sá } Capítulo 8 } Damas } Capítulo 11 } Kernighan and Ritchie } Chapter 6 32