Structures
Structure Basics A structure is a collection of data values, called data members, that form a single unit. Unlike arrays, the data members can be of different types.
Structure Definition struct name { variable declaration; . }; the keyword struct announces that this is a structure definition
Initializing Structures struct Rect { double x; double y; char color; double width; double height; }; struct rect r1 = {0,0,’r’,5,10}; x y r color 5 width 10 height
Alternate Declaration typedef struct { double x; double y; char color; double width; double height; } rect; rect r1 = {0,0,’r’,5,10}; x y r color 5 width 10 height
Accessing Data Members To access a data member use Varname.membername struct rect r1 = {0,0,’r’,5,10}; r1.x r1.y r1.color r1.width r1.height x y r color 5 width 10 height
Accessing Data Members To access a data member with a pointer use varname->membername struct rect r1 = {0,0,’r’,5,10}; struct rect *rptr=&r1; rptr->x rptr->y rptr->.color rptr->width rptr->height x y r color 5 width 10 height
Assignment operator Assignment operator is defined for structure of the same type. struct rect { double x; double y; char color; double width; double height; }; struct rect r1, r2 r1.x = 10.5; r1.y = 18.99; r1.width = 24.2; r1.height = 15.9; r1.color = 'r'; /* Copy all data from r1 to r2. */ r2 = r1;
Scope of a Structure Member variables are local to the structure. Member names are not known outside the structure.
Exercise (a,b)+(c,d)=(a+c,b+d) (a,b)*(c,d)=(a*c,b*d) Write a program using structures that manipulates pairs. Addition and multiplication of pairs is defined below. (a,b)+(c,d)=(a+c,b+d) (a,b)*(c,d)=(a*c,b*d)
Pair Structure Store two integers to represent the first and second number of pair struct pair { int first; int second; };
Addition struct pair add(struct pair p1, struct pair p2) { struct pair temp; temp.first = p1.first + p2.first; temp.second = p1.second + p2.second; return temp; }
Multiplication struct pair multiply(struct pair p1, struct pair p2) { struct pair temp; temp.first = p1.first * p2.first; temp.second = p1.second * p2.second; return temp; }
How to use the functions struct pair mp1,mp2,mp3,mp4; printf("Enter first pair\n"); scanf("%d%d",&mp1.first, &mp1.second); printf("Enter second pair\n"); scanf("%d%d",&mp2.first, &mp2.second); mp3 = add(mp1,mp2); printf("Addition result = (%d,%d)\n",mp3.first,mp3.second); mp4 = multiply(mp1,mp2); printf("Multiplication result = (%d,%d)\n",mp4.first,mp4.second);
Exercise Update the program to support the following on pairs c*(a,b) = (c*a,c*b) (a,b)^c = (a^c,b^c)
Structure Representation & Size struct CharCharInt { char c1; char c2; int i; }; struct CharCharInt foo; foo.c1 = ’a’; foo.c2 = ’b’; foo.i = 0xDEADBEEF; sizeof(struct …) = sum of sizeof(field) + alignment padding Processor- and compiler-specific 62 61 EF BE AD DE c1 c2 i padding x86 uses “little-endian” representation
Structure Representation & Size struct Rect { double x; double y; char color; double width; double height; }; struct Rect r1 = {0,0,’r’,5,10}; sizeof(r1) = sizeof (double) sizeof (char) + alignment padding Processor- and compiler-specific sizeof(r1) is 36. 4 doubles (8 bytes each)+1 char (1 byte) + 3 bytes padding
Using malloc with structures struct rect *rptr; rptr = (struct rect*)malloc(sizeof(struct rect)); rptr->x = 10.5; rptr->y = 18.99; rptr->width = 24.2; rptr->height = 15.9; rptr->color = 'r'; print(*rptr); free(rptr);
Arrays of Structures ………....... Arrays of structures may be declared in the same way as other C data types. struct rect rectangles[20]; rectangles[0] references first structure of rectangles array. rectangles[0].color = ‘r’; x y ………....... color width height 1 2 3 19
Structures as Arguments to Functions When a structure is passed as an argument to a function, it is a call-by-value reference. Changes made to the formal parameters do not change the argument. A pointer to a structure may also be passed as an argument to a function. Changes made to the formal parameters also change the argument.
Call by Value Example s s1 Updated s struct simple { int ival; double dval; }; void fun1(struct simple s) s.ival = s.ival+1; s.dval = s.dval + 2; } int main(void) struct simple s1 = {10, 1.5}; fun1(s1); printf(“%i %lf\n”, s1.ival , s1.dval ); return 0; s s1 10 10 ival 1.5 1.5 dval Updated s 11 3.5
Call by Reference Example struct simple { int ival; double dval; }; void fun1(struct simple *s) s->ival = s->ival+1; s->dval = s->dval + 2; } int main(void) struct simple s1 = {10, 1.5}; struct simple *sptr = &s1; fun1(sptr); printf(“%i %lf\n”, sptr->ival , sptr->.dval ); return 0; sptr s1 10 ival 1.5 dval s Updated s1 11 3.5
Nested Structures Structure definitions may contain data members that are other structures: struct Card { char suit; int rank; }; struct Deck struct Card cards[52]; int next_card = 0; Card suit rank 1 51 …... cards …… next_card
Initialize the Deck for (i=0; i<13; i++) for (i=26; i<39; i++) { d1.cards[i].suit = 'h'; d1.cards[i].rank = (i-26)+1; } for (i=39; i<52; i++) d1.cards[i].suit = 's'; d1.cards[i].rank = (i-39)+1; for (i=0; i<13; i++) { d1.cards[i].suit = 'c'; d1.cards[i].rank = i+1; } for (i=13; i<26; i++) d1.cards[i].suit = 'd'; d1.cards[i].rank = (i-13)+1;
Print the Deck void print(struct Deck d1) { int i; for (i=0; i<52; i++) printf("%c %d\n", d1.cards[i].suit, d1.cards[i].rank); return; }
Swap Two Cards from Deck void swap(struct Deck *ptr) { int x,y; struct Card temp; x = rand() % 52; y = rand() % 52; temp = ptr->cards[x]; ptr->cards[x] = ptr->cards[y]; ptr->cards[y] = temp; return; }
How to Shuffle the Deck? for (i=0; i<COUNT; i++) { 1 2 3 51 ………………………… for (i=0; i<COUNT; i++) { // swap two cards from Deck }
BlackJack Shuffle the deck Deal first 2 cars to user Print both cards on screen Next two cards to dealer Print only the first on screen Ask user whether he/she wants to continue Highest total <= 21 wins Jack, Queen, King are 10 points Ace is 11 points Other cards represented by their number
Unions EF BE AD DE Choices: An element is sizeof(union …) = union AnElt { int i; char c; }; union AnElt elt1, elt2; elt1.i = 4; elt2.c = ’a’; elt2.i = 0xDEADBEEF; Choices: An element is an int i or a char c sizeof(union …) = maximum of sizeof(field) EF BE AD DE c i padding
? Unions A union value doesn’t “know” which case it contains How should your program keep track whether elt1, elt2 hold an int or a char? ? union AnElt { int i; char c; }; union AnElt elt1, elt2; elt1.i = 4; elt2.c = ’a’; elt2.i = 0xDEADBEEF; if (elt1 currently has a char) … Basic answer: Another variable holds that info
Static Array Allocation struct rect rectangle[100]; Allocates space for 100 rectanges Each rectangle requires 36 bytes Allocates 3600 bytes total
Array of Pointers struct rect *rectptr[100]; Allocates an array of 100 pointers Each pointer is 4 bytes Allocates 400 bytes total Pointers do not point to allocated space
Array of Pointers for (i=0; i<100; i++) rectptr[i] = NULL; Initializes pointers to NULL
Array of Pointers for (i=0; i<100; i++) rectptr[i] = (struct rect*)malloc(sizeof(struct rect)); Allocate space so that each pointer points to a rectangle You can allocate space when you need it Allocate space for 10 rectangles if you just need 10
Array of Pointers for(i=99; i>=0; i--) free(rectptr[i]); Free the space allocated using malloc If you don’t free all the space, it will cause memory leak Space will appear as used although it is not used Used valgrind command to find memory leaks
Array of Pointers void test2(struct rect *a[]) { struct rect *temp; temp = a[0]; a[0] = a[1]; a[1] = temp; } Swaps first 2 pointers Changes are permanent since arrays are pass by reference
Array of Pointers void test(struct rect *a[]) { struct rect temp; temp = *a[0]; *a[0] = *a[1]; *a[1] = temp; } Swaps the rectangles pointed by first two pointers Changes are permanent since changed through pointers
typedef typedef struct rect rect; typedef associates a type with an identifier rect is used instead of struct rect after typedef statement Use typedef after structure declaration