C structs are like records in other programming languages. The associate a group of variables (possibly of different types) that are somehow related.
Example: a struct representing a book might relate string variables author, title and publisher; and an integer variable number of pages. In C, this struct type could be defined as follows:
#define AUTHLEN 41 #define TITLELEN 81 #define PUBLEN 81 typedef char authtype[AUTHLEN]; typedef char titletype[TITLEN]; typedef char pubtype[PUBLEN]; typedef struct { authtype author; titletype title; pubtype publisher; int numpages;} bookrec;
Here, author
, title
, publisher
and
numpages
are called the fields of the
struct. Type bookrec
is now the type of such
structs. A variable thetext
of type
bookrec
is declared as follows:
bookrec thetext;
Like arrays, a variable of a struct type can be initialized when (and only when) it is declared:
bookrec thetext = {"Barrett and Wagner", "C and UNIX", "John Wiley and Sons", 446};
The order of the initial values must match the order of the fields in the type definition.
Each field of a struct variable can be referred to by the variable name
followed by .
followed by the field name. Examples (given
the previous declaration of thetext
):
/* print the number of pages */ printf("This book has %d pages.\n", thetext.numpages); /* change the number of pages */ thetext.numpages = 448; /* read in a new publisher */ scanf("%s", thetext.publisher); /* read in a new number of pages */ scanf("%d", &thetext.numpages);
Note how addresses are handled here.
Example: a function to print a bookrec
:
void printbook(bookrec book) { printf("Author: %s\n", book.author); printf("Title: %s\n", book.title); printf("Publisher: %s\n", book.publisher); printf("Number of pages: %d\n", book.numpages); }
Functions can take structs as parameters and return structs as results.
Example: a program that handles structs representing point
s
in the real plane
#include <stdio.h> typedef struct { double x; double y; } point; point newpoint(void); void printpoint(point); main() { point p; p = newpoint(); printpoint(p); } point newpoint(void) { /* return an initialized point */ point tp; tp.x = 0; tp.y = 0; return (tp); } void printpoint(point tp) { /* print a point */ printf("The point value is: (%lf, %lf).\n", tp.x, tp.y); }
Structs are passed by value by default, so a function that needs to change some field(s) of a struct must have a parameter of type address of struct.
Example: a function to set the x
field of a point
void setx(point *paddr, double newval) { /* set the x field to newval */ (*paddr).x = newval; }
Note that we first get the value at the address of the struct, and then
refer to the field. C also provides the ->
operator to
refer to fields of a struct parameter that has been passed by address:
void setx(point *paddr, double newval) { /* set the x field to newval */ paddr->x = newval; }
Example: see ~taw2/pub/struct.c
Structs can:
Example. The following makes librarytype
the type of arrays of
bookrec
s (a library of books):
#define AUTHLEN 41 #define TITLELEN 81 #define PUBLEN 81 #define LIB_MAX 100 typedef char authtype[AUTHLEN]; typedef char titletype[TITLEN]; typedef char pubtype[PUBLEN]; typedef struct { authtype author; titletype title; pubtype publisher; int numpages;} bookrec; typedef bookrec librarytype[LIB_MAX]; /* some expressions using this type */ /* declare a variable of type librarytype */ librarytype library; /* how many pages does the third book in the library have? */ printf("Number of pages: %d\n", library[2].numpages); /* add 5 pages to the 10th book in the library */ library[9].numpages += 5; /* read in a new author for the second book in the library */ scanf("%s", library[1].author);
Example: see ~taw2/pub/library.c
Structs can be declared without using a typedef
by using a
tagname that appears between struct
and {
.
Example:
struct point { double x; double y; };
Here, point
is the tagname. To use this struct type, the
keyword struct
must be used with it in declarations and prototypes.
Examples:
struct point point1, point2; void setx(struct point *paddr);
This syntax is will be useful in the future. A typedef
can still
be used along with this way of defining struct types:
typedef struct point pointtype;
makes struct point
and pointtype
equivalent type
names.