Arrays and pointers are nice for lists of values, but those values must all be of the same data type. There will be times when you have different data types that must go together and be treated as a whole.
A perfect example is a customer record. For each customer, you would have to track a name (character array), balance (double floating-point), address (character array), city (character array), state (character array), and zip code (character array or long integer). Although you would want to be able to initialize and print individual items within the customer record, you would also want to access the customer record as a whole, such as when you would write it to a customer disk file (which is explained in the next chapter).
The C structure is the vehicle by which you group data such as would appear in a customer record, and get to all the individual parts, called members. If you have many occurrences of that data and many customers, you would need an array of structures.
Other programming languages have equivalent data groupings called records. The designers of C wanted to call these data groupings structures, however, so that’s what they are in C.
Many times, a C structure holds data that you might store on 3×5 cards in a cardfile. Without a computer, a company might very well maintain a cardfile box with cards that contain a customer’s name, balance, address, city, state, and zip code, like the customer structure just described. Later in this chapter, you’ll see how C structures are stored in memory, and you’ll see even more similarities to the cardfile cards.
The first thing you must do is tell C exactly what your structure will look like. When you define variables of built-in data types such as int
s, you don’t have to tell C what an int
is because C already knows. When you want to define a structure, however, you must first tell C exactly what your structure looks like. Then and only then can you define variables for that structure.
Not only is a structure like a cardfile, but you also can see that a structure is a lot like a paper form with blanks to fill in. A blank form, such as one you might fill out when applying for a credit card, is useless by itself. If the credit card company prints 10,000 forms, that doesn’t mean they have 10,000 customers. Only when someone fills out the form is there a customer, and only when you define a variable for the structure you describe will C give memory space to a structure variable.
To define an int
variable, you only have to do this:
int i;
You don’t first have to tell C what an int
is. To define a structure variable, you must first define what the structure looks like and assign a data type name, such as customer
, to C. After defining the structure’s format, you can define a variable.
The struct
statement defines the look (or layout) of a structure. Here is the format of struct
:
Again, the struct
defines only the layout, or the look, of a structure. The structure tag
is a name you give to that particular structure’s look, but the structure tag
has nothing to do with a structure variable name you might create later. After you define the format of a structure, you can define variables.
The member definitions
are nothing more than regular built-in data type definitions such as int age;
. Instead of defining variables, though, you are defining members, in effect giving a name to that particular part of the structure.
You can define a variable at the same time as the struct
declaration statement, but most C programmers don’t do so. If you want to define a variable for the structure at the same time you declare the structure format itself, insert one or more variable names before the struct
statement’s closing semicolon.
Let’s say you’re writing a program to track a simple retail computer inventory. You need to track a computer manufacturer, model, amount of disk space (in megabytes), amount of memory space (in megabytes), quantity, cost, and retail price.
First you must use struct
to define a structure. Here is a good candidate:
Figure 27.1 shows you what this structure format looks like.
Figure 27.1. The format of the invStruct
structure.
The previous structure definition does not define seven variables! The previous structure definition defines a single structure data type. Remember, you don’t have to tell C what an integer looks like before defining an integer variable; you must, however, tell C what an invStruct
looks like before defining variables for that structure data type. The previous struct
statement tells C what the user’s invStruct
is supposed to look like. Once C learns the structure’s format, C can then define variables that take on the format of that structure when the user is ready to define variables.
If you create a structure that you might use again sometime, consider putting it in its own header file, or in a header file along with other common structures. Use #include
to pull that header file into any source code that needs it. If you ever need to change the structure definition, you have to look in only one place to change it—in its header file.
Often, a programmer puts structure declarations, such as the previous one for invStruct
, before main()
and then defines variables for that structure in main()
and in any other functions below main()
. To create variables for the structure, you must do the same thing you do when you create variables for any data type: Put the structure name before a variable list. Because there is no data type named invStruct
, you must tell C that invStruct
is a struct
name. You can define three structure variables like this:
Now there are three variables into which you can put data. These variables are structure variables named item1
, item2
, and item3
. If you wanted to define 500 structure variables, you would use an array:
Remember, the structure definition must go in the INV.H header file if you take this approach. Otherwise, you must place the structure definition directly inside the program before the structure variables like this:
As long as the struct
definition appears before main()
, you can define invStruct
structure variables throughout the rest of the program in any function you write. (The last part of this book explains how to write programs that contain more functions than main()
.)
Perhaps you will need pointers to three structures instead of structure variables? Define them like this:
item1
, item2
, and item3
now can point to three structure variables. You can then reserve heap memory for the structures instead of using actual variables. (sizeof()
works for structure variables to allow for heap structure data.) The following three statements reserve three heap structure areas and makes item1
, item2
, and item3
point to those three heap values:
A new operator, the dot operator, lets you put data in a structure variable’s individual members. Here is the format of the dot operator:
structureVariableName.memberName
To the left of the dot is always the name of a structure variable, such as item1
or employee[16]
. To the right of the dot operator is always the name of a member from that structure, such as quantity
, cost
, or name
. The dot operator puts data only in named structure variables. If you want to put data in a heap structure pointed to by a structure pointer variable, you must use the structure pointer operator, ->
.
The following program defines an array of three structure variables using the invStruct
structure tag shown earlier. (The structure is assumed to be stored in INV.H to keep the example short.) The user is asked to fill the structure variables, and then the program prints them. In the next couple of chapters, you’ll see how to output the structure variables to a disk file for long-term storage.
If you were to store the structures on the heap, you couldn’t use the dot operator, because the dot operator requires a variable name. Use ->
to store data in heap structures. ->
requires a pointer on the left and a member name on the right. Here is an equivalent program to the previous one, except the heap and ->
are used instead of structure variables and the dot operator.
• Define structures when you want to group items of different data types.
• Declare a structure before defining a structure variable.
• Use the dot operator to access individual data members within a structure variable.
• Use the ->
(the structure pointer operator) to access individual data members within a structure pointed to by a pointer variable.
• Don’t use member names as variables. Member names exist only so you can work with an individual part of a structure.
• Don’t forget to add a semicolon at the end of all structure definitions.
• Don’t intermix the dot operator and the structure pointer operator. Remember that a structure variable must appear before the dot operator, and a structure pointer variable must appear before the ->
operator.
This chapter’s goal was to teach you about structures. A structure is an aggregate variable data type. Whereas an array must hold values that are all the same data type, a structure can hold several values of different data types.
Before using a structure variable, you must tell C exactly what the structure looks like with a struct
statement. The struct
statement lets C know how many members are in the structure and the data types of each member. A structure variable is like a group of more than one variable of different data types.
This code might be the start of a program that tracks telephone numbers and addresses of your friends. The code first describes a structure that has nine members. The members are made up of character arrays, a character member, an integer member, and a long integer member.
The program that begins in main()
defines an array of 50 structure variables. (An int
variable is also defined just to show you that structures are defined in the same location as other variables.) Each of the 50 structure variables has the telStr
layout.