Download presentation
Presentation is loading. Please wait.
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
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; }; x y x y x y
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); 34 ax==3ay==4
9
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); x=??? y=??? 34 ax==3ay==4
10
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); 34 ax==3ay==4 x=??? y=???
11
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); x==3 y==4 34 ax==3ay==4
12
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); x==3 y==4 34 ax==3ay==4
13
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); x==3 y==4 34 ax==3ay==4 x==3 y==4
14
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); x==3 y==4 p 34
15
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 x==3 y==4
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
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 x==3 y==4
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
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; }; data next data next data 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
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. i, a[0] a[1]
22
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 == ??? i, a[0] a[1]
23
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] = ??? i, a[0] a[1]
24
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]); } i, a[0] 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
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; }; i, a[0] a[1] tag
27
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; i, a[0] a[1] tag
28
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… } } i, a[0] a[1] tag
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’‘a’ ? ? ? ? p 1000 1001 1002 1003 1004
38
Example int sum (int x, int y) { int temp = x + y; return temp; } int main () { char *s = (char *)sum; return 0; } temp=x+y ? return temp ? sum: 1000 1004 1008 1012 1016 s
39
Example int sum (int x, int y) { int temp = x + y; return temp; } int main () { char *s = (char *)sum; char a[100]; return 0; } temp=x+y ? return temp ? sum: 1000 1004 1008 1012 1016 s
40
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; } temp=x+y ? return temp ? sum: 1000 1004 1008 1012 1016 s
41
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; } temp=x+y ? return temp ? sum: 1000 1004 1008 1012 1016 s int sum (int x, int y) { int temp = x + y; return temp; }
42
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; } temp=x+y ? return temp ? sum: 1000 1004 1008 1012 1016 s int sum (int x, int y) { int temp = x + y; return temp; }
43
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; } temp=x+y ? return temp ? sum: 1000 1004 1008 1012 1016 s 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 unsigned int 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; };
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.