1 / 49

Structures

Structures. C and Data Structures Baojian Hua bjhua@ustc.edu.cn. Why need “ Structure ” ?. So far, we ’ d discussed two kinds of data: Simple: char, int, long, double, etc. Scalar: array, pointer, etc. It ’ s inconvenient in some applications: See next slides for an example. Example.

Download Presentation

Structures

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Structures C and Data Structures Baojian Hua bjhua@ustc.edu.cn

  2. Why need “Structure”? • So far, we’d discussed two kinds of data: • Simple: char, int, long, double, etc. • Scalar: array, pointer, etc. • It’s inconvenient in some applications: • See next slides for an example

  3. Example // We want to represent time as year/month/date: int f () { int year1, year2, month, date; year1 = 2050; year2 = 2020; month = 12; date = 30; date++; // Should we increase year1 or year2? } // The problem is that there is no logical // connection between them. We need “structure”!

  4. Structure Declaration // Start with key word “struct” and followed by // an optional structure tag, and then a list // (one or more) of fields. // Example, to represent a two-dimensional point: struct point2d { int x; int y; }; // note the semicolon // point2d contains two fields x and y, both of // type int. // struct point2d (as a whole) is a (user-defined) // new type.

  5. Variable Definition // Given the declaration above, we may declare a // variable pt: struct point2d pt; // to be of type “struct point2d”, just the same // way as we write: int i;

  6. Structure Fields // Given the variable definition struct point2d pt; // fetching its fields x or y: pt.x; pt.y; // which act as ordinary variables, such as: pt.x = 9; pt.y = 10; // or: printf (“%d\n”, pt.x + pt.y);

  7. x x x y y y Structure in Structure // Having known that structures are types, we may // study its memory layout. Technically, a // structure occupies a piece of continuous space: // So, we may even nest structures // in other structures, as in: struct rect { struct point2d pt1; struct point2d pt2; };

  8. Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); ax==3 ay==4 3 4

  9. x=??? y=??? Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); ax==3 ay==4 3 4

  10. x=??? y=??? Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); ax==3 ay==4 3 4

  11. x==3 y==4 Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); ax==3 ay==4 3 4

  12. x==3 y==4 Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); ax==3 ay==4 3 4

  13. x==3 x==3 y==4 y==4 Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); ax==3 ay==4 3 4

  14. x==3 y==4 Structures and Functions // A function creating a point2d structure: struct point2d create (int ax, int ay) { struct point2d pt; pt.x = ax; pt.y = ay; return pt; } // And a sample call: struct point2d p = create (3, 4); p 3 4

  15. x==3 y==4 Structures as Functions Arguments // Like the structure return value, passing // structures to functions copy the whole // structure field-by-field (call-by-value): struct point2d mult2 (struct point2d pt) { pt.x *= 2; pt.y *= 2; return pt; } // A sample call: struct point2d p = mult2 (initPt); // Much like the previous example // Analysis leave to you

  16. Moral • Structures returned from function and passed to functions are call-by-value • Pros: a simple style of functional programming • result in elegant and easy-to-reason code • ideas from functional languages (lisp, ML, F#), but may also be useful in imperative and OO languages • Cons: may be too inefficient • stupidly copy a big value • semantics inconsistent with array • Next, we’d discuss a more imperative style • Update in place

  17. x==3 y==4 Pointers to Structures // Pointers to structures are just like pointers // to any other kind of data: struct point2d *pt; // declares pt to be a pointer to a structure // ponit2d, which looks like: // To reference x and y, we use: (*pt).x; (*pt).y; // or a more concise shorthand: pt->x; pt->y; pt

  18. Structure Pointers as Functions Arguments // Address passing: void mult2 (struct point2d *pt) { pt->x *= 2; pt->y *= 2; return; } // A sample call (no return value): struct point2d p = creat (3, 4); mult2 (&initPt); // Analysis leave to you

  19. data data data next next next Self-referential Structures // With structures pointer mechanism, we may // write self-referential structures (structures // fields point to same type of structures): struct node { int data; struct node *next; };

  20. Union • A union may hold (at different times) objects of different types and sizes • compilers take care of the space allocation, alignment, etc. • Unions provide a way to manipulate different kinds of data in a single area of storage

  21. i, a[0] a[1] Union // A sample union type: union intOrArray { int i; int a[2]; }; // which declares intOrArray to have two fields: // integer i and int array a of length 2.

  22. i, a[0] a[1] Union // A sample union type: union intOrArray { int i; int a[2]; }; // which declares intOrArray to have two fields: // integer i and int array a of length 2. union intOrArray u; u.a[0] = 88; u.a[1] = 99; // u.i == ???

  23. i, a[0] a[1] Union // A sample union type: union intOrArray { int i; int a[2]; }; // which declares intOrArray to have two fields: // integer i and int array a of length 2. union intOrArray u; u.i = 77;; // u.a[2] = ???

  24. i, a[0] a[1] Union // A sample union type: union intOrArray { int i; int a[2]; }; // Even worse. What if we write an “output”? void output (union intOrArray x) { printf (“%d\n”, x.i); // or: printf (“%d, %d\n”, x.a[0], x.a[1]); }

  25. Moral on Union • Union gives us a magical bag to let us bypass the C’s type system • store an integer, but take out an array • It’s the programmers’ responsibility to keep union data consistent • But what if the union value is written by others or from a library, which we may know nothing about?

  26. tag i, a[0] a[1] Tagged Union // In order to distinguish union states, we // annotate unions with tags: struct ss { enum {INT, ARRAY} tag; union intOrArray { int i; int a[2]; } u; };

  27. tag i, a[0] a[1] Tagged Union // And for variable temp: struct ss temp; // now we must take care of temp’s tag fields: temp.u.i = 99; temp.tag = INT; // Or to store an array: temp.u.a[0] = 3; temp.u.a[1] = 4; temp.tag = ARRAY;

  28. tag i, a[0] a[1] Tagged Union // data accessing is guarded: void output (struct ss x) { switch (x.tag) { case INT: printf (“%d”, x.u.i); break; case ARRAY: printf (“%d, %d”, x.u.a[0], x.u.a[1]); break; default: // error handling… } }

  29. typedef---Define Our Own Types • And it’s rather stupid and annoying to always write long type names like these: struct point2d pt; struct point2d *pp; • And even some types are rather crazy: int (*f[10])(int, int); int (*f(char c))(int, int); • Are there some better methods? • Yes! It’s the “typedef”

  30. typedef---Define Our Own Types // C has a mechanism called “typedef” allowing us // to define our own types (abbreviations). // For instance: typedef struct point2d pt2d; // defines “pt2d” to be a type equivalent to // “struct point2d”. And next, “pt2d” could be // used just as any other type: pt2d pt; pt.x = 3; pt.y = 4;

  31. typedef---Define Our Own Types // Not only structures can be typedefed, but also // any type name, even the pre-defined ones in C: typedef int sizeT; sizeT i; i = sizeof (int); sizeT j; j = i;

  32. typedef---Define Our Own Types // More examples of typedef: typedef int *t1; typedef int (*t2)(); typedef char **t3; typedef int *t4[10]; typedef int (*t5)[10]; typedef int *t6(); typedef char (*(*t7())[])(); typedef (*(*t8[3])())[5];

  33. typedef---Define Our Own Types // More examples of typedef: typedef int *t1; typedef int (*t2)(); typedef char **t3; typedef int *t4[10]; typedef int (*t5)[10]; typedef int *t6(); typedef char (*(*t7())[])(); typedef char (*(*t8[3])())[5]; // How to read these crazy stuffs? // Next, to show the general principal, I’ll take // type t7 as a running example:

  34. Inorder Analysis typedef char (*(*t7())[])(); // t7 is a function, takes void // function returns a pointer // pointing to an array // array storing pointers // pointing to functions (taking void returning // char) // Really annoying! Better solutions? Yes!

  35. Preorder typedef char (*(*t7())[])(); // Step by step: typedef char (*t71)(); typedef t71 t72[]; typedef t72 *t7(); // Question: How to rewrite t8?

  36. Type Cast Revisit • We’d discussed type cast • Ex: (int)3.14 • unsafe in general • Type cast on pointers is more flexible, subtle, and dangerous • we’d discuss an example below

  37. Type Cast on Pointers char c = ‘a’; char *p = &c; int *q = (int *)p; *q = 9999; short *r = (short *)q; *r = 88; ‘a’ 1000 ? 1001 p ? 1002 ? 1003 ? 1004

  38. 1000 s sum: temp=x+y 1004 return temp 1008 ? 1012 ? 1016 Example int sum (int x, int y) { int temp = x + y; return temp; } int main () { char *s = (char *)sum; return 0; }

  39. 1000 s sum: temp=x+y 1004 return temp 1008 ? 1012 ? 1016 Example int sum (int x, int y) { int temp = x + y; return temp; } int main () { char *s = (char *)sum; char a[100]; return 0; }

  40. 1000 s sum: temp=x+y 1004 return temp 1008 ? 1012 ? 1016 Example int sum (int x, int y) { int temp = x + y; return temp; } int main () { char *s = (char *)sum; char a[100]; int i; for (i=0; i<100; i++) a[i] = s[i]; return 0; }

  41. 1000 s sum: temp=x+y 1004 return temp 1008 ? 1012 ? 1016 Example int main () { char *s = (char *)sum; char a[100]; int i; for (i=0; i<100; i++) a[i] = s[i]; // call array a? return 0; } int sum (int x, int y) { int temp = x + y; return temp; }

  42. 1000 s sum: temp=x+y 1004 return temp 1008 ? 1012 ? 1016 Example int main () { char *s = (char *)sum; char a[100]; int i; for (i=0; i<100; i++) a[i] = s[i]; // call array a? a(3, 4); return 0; } int sum (int x, int y) { int temp = x + y; return temp; }

  43. 1000 s sum: temp=x+y 1004 return temp 1008 ? 1012 ? 1016 An Array Can be Called! typedef int (*tf)(int, int); int main () { char *s = (char *)sum; char a[100]; int i; for (i=0; i<100; i++) a[i] = s[i]; // call array a? (tf(a)) (3, 4); return 0; } int sum (int x, int y) { int temp = x + y; return temp; }

  44. Summary of Typedefs • typedef doesn’t create any new type name • it creates shorthands for known types • typedef is an important mechanism: • to make program maintenance and porting easy • to enable information hiding • more on this later

  45. Bit-fields // What’s bit-fields, and why do we want them? // We start by defining a student structure: struct student { char *name; int gender; // 0 or 1 int classNum; // 0~7 int isLeader; // 0 or 1 }; // See the problem?

  46. Bit-fields // To save space, We use bit-fields: struct student { char *name; unsigned int gender : 1; // 0 or 1 unsigned int classNum : 3; // 0~7 unsignedint isLeader : 1; // 0 or 1 }; // Question: what the size of “struct student”?

  47. Bit-fields // Sample operations: #define FEMALE 0x00 #define MALE 0x01 #define CLASS1 0x00 … #define CLASS8 0x07 struct student s; s.name = “Bill Gates”; s.gender = MALE; s.classNum = CLASS0; s.isLeader = 0x00;

  48. Bit-fields for Data // Besides saving space, some externally-imposed // data formats require compact data rep’. // As a final example in this slide, we discuss // x86’s interrupt descriptor (id):

  49. Bit-fields for Data struct idtEntry { unsigned int offset0_15 : 16; unsigned int selector : 16; unsigned int notUsed : 5; unsigned int zeros : 3; unsigned int reserved : 5; unsigned int dpl : 2; unsigned int p : 1; unsigned int offset16_31 : 16; };

More Related