A structure defines a new data type, made up of elements called 'members.'
Each member within a struct is identified with a unique name and may be of any type. (Unlike an array, the elements of a struct may be values of different types.)struct structure_tag { type1 name1; type2 name2; etc... } optional_variable_list;
/* define a struct */
struct point {
double x;
double y;
};
/* declare a couple variables */
struct point first, second;
/* initialize a struct point variable */
first.x = 2.3; /* use '.' to identify a member of a struct */
first.y = 6.7;
/* you can assign the values stored in one struct to another */
second = first;
/* 'second' is a completely separate copy of the values (2.3,6.7), so: */
second.y = 5.2; /* second.y is now 5.2, but first.y is still 6.7 */
/* you can also assign values with the following syntax */
first = {2.6, 7.9}; /* x is 2.6, y is 7.9 */
struct point {
double x;
double y;
} first, second;
Suppose you want to write a function to print a point. What kind
of value should it return? What should its argument be? How would you
write a printf statement to print a point? Put the answers to these
questions
together and you've got your function:
void printPoint (struct point p) {
printf("(%f, %f)", p.x, p.y);
}
Typedef defines a new data type by giving a new name to an already defined type.
old_name new_name;
typedef double real; /*suppose you didn't like remembering that you can define 'real' values with the double type*/ real r, s; /* you can declare variables to be of type real (even though they're just doubles) */
typedef struct {
double x;
double y;
} point;
point first, second; /* 2 variables of type point */
main pageWith this newly defined point type, the printPoint function defined in the previous section would need to be changed slightly. Modify the argument list from 'struct point p' to just 'point p.' Everything else would stay the same. Here is an example of another function that uses the point type. It calculates the distance between 2 points. (The math.h library is required for the sqrt function.)
double distance (point p1, point p2) { double dx, dy; dx = p1.x - p2.x; dy = p1.y - p2.y; return sqrt(dx*dx + dy*dy); }Once you've defined a new data type, like point, it's easier to create more complex types, such as rectangles, or triangles. Compare these two definitions for a triangle data type:
typedef struct { typedef struct { point v1; double v1x, v1y; point v2; double v2x, v2y; point v3; double v3x, v3y; } triangle; } triangle;Now, with the first definition, we can write a function that calculates the perimeter of a triangle like this:
double perimeter (triangle t) { return distance(t.v1,t.v2) + distance(t.v2,t.v3) + distance(t.v1,t.v3); }But writing the function for the second definition of a triangle is more complicated:
double perimeter(triange t) { double side1, side2, side3; double dx, dy; dx = t.v1x - t.v2x; dy = t.v1y - t.v2y; side1 = sqrt(dx*dx + dy*dy); dx = t.v2x - t.v3x; dy = t.v2y - t.v3y; side2 = sqrt(dx*dx + dy*dy); dx = t.v1x - t.v3x; dy = t.v1y - t.v3y; side3 = sqrt(dx*dx + dy*dy); return side1 + side2 + side3; }While this function does exactly the same thing as the simpler perimeter function, there's a much greater chance that you'd make an error while typing the second version. I could have easily mixed-up vertex numbers or x's & y's. And this type of error is harder to spot. Besides illustrating the usage of struct and typedef, this example also demonstrates the advantages of modular programming.