240 likes | 254 Views
Learn how to use structure declaration, definition, accessing elements, pointers, indirection, and utility functions in C programming with examples and best practices.
E N D
Structure Declaration • Creates a user-defined data type. • Gives the compiler a “head’s up” as to what the structure contains. • Does NOT create an instance of a structure. • Does NOT allocate any memory.
tag keyword structure elements braces surround element declarations semicolon required Structure Declaration Example struct pt3d { int pt; double x, y, z; };
Structure Definition • Creates an instance of a structure. • Allocates memory. • Associates a variable name with that instance. • Directly analogous to defining a variable of any of the pre-defined data types.
variable name(s) variable type array variable Structure Definition Example int main(void) { int i; struct pt3d pt1, pt2; struct pt3d pt[5]; .... return 0; }
Typedef simplifies the syntax • Almost identical to #define statement. • Performs text replacement. • “distributes” any pointer de-reference operators. Syntax: typedef data-type alias; Example: typedef unsigned int size_t; typedef struct pt3d PT3D;
Everything to this point Typedef can appear before structure declaration typedef struct pt3d PT3D; struct pt3d { int pt; double x, y, z; }; int main(void) { int i; PT3D pt1; PT3D pt[5]; .... return 0; } Structure declaration outside any function to make it have global scope
Accessing Elements • Similar to accessing elements of an array. • Array: Follow the name of the array with the “structure access operator” (square brackets) surrounding the offset of the element to be accessed. • Structure: Follow the name of the structure with the “member access operator” (a period) followed by the name of the element to be accessed. • Use the accessed element just like a plain variable of that same type.
Accessing Elements Examples int j; int k[12]; PT3D point; j = 5; k[j] = 42; point.pt = k[j]; j = point.pt + 3;
Pointers to Structures • Work just like pointers to other data types. • Use the “indirection operator” (asterisk) to “de-reference) the pointer in order to get at the value being pointed to. • Treat the dereferenced pointer the same as the name of a variable of the type being pointed to.
Structure Pointer Examples int j, *m; int k[12]; PT3D point, *p; m = &j; p = &point; *m = 5; // same as j = 5; k[j] = 42; (*p).pt = k[j]; // same as point.pt = k[j]; j = (*p).pt + 3; // same as j = point.pt + 3;
Why (*p).pt and not just *p.pt ? • Highest precedence operators: (), [], ., -> • De-reference is second in precedence. • The code fragment: *p.pt compiles as *(p.pt) • The operand on the left side of the member access operator must be a variable of structure type. • But p is not a variable of structure type - it points to a variable of structure type. • So we must override the precedence and force the pointer to be de-referenced first using parentheses.
Structure Indirection • De-referencing structure pointers very common. • Failing to override operator precedence very common. • A different operator is available specifically for this purpose. • If the left operand is a structure to a pointer, then the “structure indirection operator” (a hyphen followed immediately by a greater-than symbol) will first de-reference the pointer and then access the indicated element. • The code : p->pt compiles as (*p).pt
Primitive and Utility Functions • Structure elements frequently change. • Sloppy use of structures becomes a code maintenance nightmare. • Primitive and Utility functions provide a localized interface to a structure’s elements. • ONLY the primitive function should ever directly access the structure elements. • ONLY the utility functions should ever call the primitive functions. • The programmer should only use utility (and higher) functions.
Get()/Set() Primitive Functions • One Get()/Set() Pair for each structure element. • Get() functions read the current value. • Set() functions write a new value. • Both return the final value. • Work best if structures passed by reference.
Get()/Set() list for PT3D int GetPT3D_pt(PT3D *p); int SetPT3D_pt(PT3D *p, int v); double GetPT3D_x(PT3D *p); double SetPT3D_x(PT3D *p, double v); double GetPT3D_y(PT3D *p); double SetPT3D_y(PT3D *p, double v); double GetPT3D_z(PT3D *p); double SetPT3D_z(PT3D *p, double v);
element name element type NULL check Set() calls the Get() to return value Get()/Set() Primitive Functions Naming convention: Get[STRUCT]_[element] int GetPT3D_pt(PT3D *p) { if (NULL == p) return -1; return p->pt; } int SetPT3D_pt(PT3D *p, int v) { if (NULL == p) return -1; p->pt = v; return GetPT3D_pt(p); }
Utility Function - set all the point coordinates at once. PT3D NewPoint(int pt, double x, double y, double z) { PT3D temp; SetPT3D_pt(&temp, pt); SetPT3D_x(&temp, x); SetPT3D_y(&temp, y); SetPT3D_z(&temp, z); return temp; }
Utility Function - subtract two points (vector between points). PT3D SubtractPT3D(PT3D ptA, PT3D ptB) { PT3D temp; SetPT3D_pt(&temp, 0); SetPT3D_x(&temp, GetPT3D_x(&ptA) - GetPT3D_x(&ptB) ); SetPT3D_y(&temp, GetPT3D_y(&ptA) - GetPT3D_y(&ptB)); SetPT3D_z(&temp, GetPT3D_z(&ptA) - GetPT3D_z(&ptB)); return temp; }
Utility Function - Distance between two points double DistanceBetweenPT3D(PT3D ptA, PT3D ptB) { double distance; distance = LengthPT3D(SubtractPT3D(ptA, ptB)); return distance; }
Utility Function - Distance between two points double LengthPT3D(PT3D ptA) { double length; int i; for (i = 0, length = 0.0; i < 3; i++) length += pow(GetPT3D_dimensionN(&ptA, i),2); return sqrt(length); }
Utility Function - Get coordinate of a point based on index double GetPT3D_dimensionN(PT3D *p, int i) { if (NULL == p) return -1; switch (i) { case 0: return GetPT3D_x(p); break; case 1: return GetPT3D_y(p); break; case 2: return GetPT3D_z(p); break; } return -2; }
Simple main() #define PTS (5) int main(void) { int i; PT3D pt[PTS+1]; double theta; for (i = 0; i <= PTS; i++) { theta = i * (2.0*PI/(double) PTS); pt[i] = NewPoint(i, cos(theta), sin(theta), 0.0); fprintPT3D(stdout, pt[i]); } return 0; }
Utility function to print structure to a file. void fprintPT3D(FILE *fp, PT3D pt) { int i; fprintf(fp, “%i”, GetPT3D_pt(&pt)); for (i = 0; i <= 3; i++) fprintf(fp, “, %f”, GetPT3D_dimensionN(&pt, i)); fprintf(fp, “\n”); }