Chapter 11
Structures and Unions
A structure is a collection of
one or more variables, possibly of di erent types, grouped together under a
single name for convenient handling. ... Structures help to organise
complicated data, particularly in large programs, because they permit a group of
related variables to be treated as a unit instead of as separate entities [KR88,
page 127].
The C language provides means
to create user-defined types called structures. These types are
aggregates of basic types and other user-defined types, and permit a logical
grouping of related data. This chapter discusses structures, their operations
and implications, and the associated topics of type-definitions and unions.
11.1 Structures
A structure is declared using
the keyword struct,
and the internal organisation of the structure is defined by a set of variables
enclosed in braces. Consider the following example, which declares a structure
for representing two-dimensional points.
struct Point {
int x;
int y;
};
Style Note. By convention,
structures should always be named with an uppercase first letter. This
distinguishes them from variables and functions (lowercase first letter), and
symbolic constants (all uppercase).
The
variables x
and y are called members
of the structure named Point.
Variables of type Point
may be defined as a list of identifiers at the end of the struct definition,
struct Point {
int x;
int y;
} p1, p2, p3;
/* Define three variables of type Point. */
or as subsequent definitions using
the tag “struct Point”.
struct Point
p1, p2, p3; /* Define three variables of type Point. */
When a structure is defined, its
members may be initialised using brace notation as follows.
struct Point
topleft = { 320, 0 };
Here
the member x
is initialised to 320 and the member y
to 0. In general, the values within the initialiser list correspond to the
structure member variables in order of their declaration.
Individual members of a struct
may be accessed via the member operator “.”. For
example,
struct Point
topleft;
topleft.x =
320;
topleft.y = 0;
is an alternative way to
initialise the variable topleft. Thus, we might
compute the distance between two points pt1
and pt2, using the
standard library function sqrt(),
as shown below.
struct Point
delta = { pt1.x - pt2.x, pt1.y - pt2.y };
double distance
= sqrt((double)delta.x * delta.x + (double)delta.y * delta.y);
Structures can be nested, such
that the definition of one structure type may be composed, in part, of another
structure type. For example, a rectangle might be described by its top-left and
bottom-right corners as follows.
struct
Rectangle {
struct Point
topleft;
struct Point
bottomright;
};
To access the lowest-level
members of a variable of type Rectangle,
therefore, requires two instances of the member operator.
struct
Rectangle rect;
rect.topleft.x
= 50;
11.2 Operations on Structures
The operations permitted on
structures are a subset of the operations permitted on basic types (such as int, double, etc). Structures
may be copied or assigned, but it is not possible to directly compare two
structures.
struct Point p1
= { 0, 0 };
struct Point
p2;
p2
|
= p1;
|
/*
|
Valid.
structs
|
may be
assigned. */
|
|
if (p1 == p2)
|
/*
|
Invalid.
structs may not be compared. */
|
|||
printf("Points
|
are
|
equal\n");
|
|||
if
|
(p1.x == p2.x
&& p1.y == p2.y)
|
/* Valid. May
compare basic types. */
|
|||
printf("Points
|
are
|
equal\n");
|
A structure may be passed to a
function and may be returned by a function.
struct Point
point_difference(struct Point p1, struct Point p2)
/* Return the
delta (dx, dy) of p2 with respect to p1. */
{
p2.x -= p1.x;
p2.y -= p1.y;
return p2;
}
As with any other variable,
structures are passed by value. Thus, in the above example, p1 and p2 are copies of the passed
arguments, and the changes to p2 within
the function do not a ect the value
of the associated variable in the calling function.
struct Point a
= {5,10}, b = {20,30}, c;
c =
point_difference(a, b); /* c = {15,20}, b is unchanged. */
Passing
structures by value can be ine cient if the structure is large, and it is
generally more e cient to pass a pointer to a struct rather than making a copy. Defining structure pointers and
obtaining the address of a struct
variable is the same as for basic types.
struct Point pt
= { 50, 50 };
struct Point
*pp;
pp = &pt;
(*pp).x = 100;
/* pt.x is now 100. */
Note, the parentheses about (*pp).x are necessary to
enforce the correct order-of-evaluation, so that the pointer-to-struct is dereferenced before
attempting to access member x.
To avoid this rather complicated dereferencing syntax, an alternative notation
is provided to access structure members via a pointer. The -> operator permits
the expression (*pp).x
to be rewritten more simply as pp->x.
As a further example, given the
variable definitions
struct
Rectangle rect, *pr = ▭
the following statements are
equivalent.
rect.topleft.x
= 50;
(*pr).topleft.x
= 50;
pr->topleft.x
= 50;
No comments:
Post a Comment