Lesson 09: Structures
Lesson 07: Arrays introduced the array that allow you to group elements of the same type into a single logical entity. To access elements in an array, all that is necessary is that the name of the array is given together with the appropriate index value.
The C/C++ language provides another method for grouping elements together. This falls under the name of structures and forms the basis for the discussions in this lesson.
9.1 Structures
The struct keyword is used to create an aggregate data type called a structure. A structure is a collection of one or more data members (variables). The data members in a structure can be of different types: Some can be int, some can be float, and some can be another struct, and so on. Structure in C/C++ is unlike the array, in which all the variables must be the same type.
There are many situations in which we want to process data about a certain entity or object, but the data consists of items of various types. For example, the data for a student (the student record) may consist of several fields such as a name, address, phone number (all are strings), number of courses taken (integer), fees payable (floating-point), student ID (string), grades obtained (character), and so on.
Suppose we want to store data for 30 students in a program. One solution is to have a separate array for each field and use subscripts to link the fields together. Thus, name[i], address[i], fees[i], and so on, refer to the data for the ith student.
The problem with this solution is that if there are many fields, handling several parallel arrays becomes clumsy and unwieldy. For example, we want to pass a student's data to a function via the parameter list, which will involve the passing of several arrays. Also, when we are sorting the data by name field, we have to change the data in the other arrays when two names are swapped. In such situations, C structures are convenient to use.
In C++, a structure can contain both function and data members. The detailed structure in C++ will be discussed in C++ Lesson 02: Classes and Objects.
The format of the struct statement is as follows:
struct structure_name {
type member1;
type member2;
...
} variable_list;
Declare Structure and Structure Variables
A structure variable can either be declared with a structure declaration or a separate declaration like how we declare a variable.
Structure declaration
struct Point { // Structure Declaration int x; int y; };
The above statement defines a new data type (struct Point) that can be used in declaring other variables as below:
struct Point p1, p2, p3;
A variable declaration with structure declaration.
struct Point { // Structure Declaration int x; int y; } p1; // Define Structure Variable
The above definition actually tells the C compiler two things:
- The first one is the structure of a "struct Point", which can be used to declare another structure variable.
- This statement also declares the variable p1ent.
Since the structure of "struct Point" has been defined, so it can use that to declare additional variables:
struct Point p2, p3;
Use of typedef in structure to shorten the names
We also can use typedef to construct shorter or more meaningful names for structures. The following code shows a new data type name Point, which is synonymous with "struct Point":
typedef struct Point { // Structure Point Declaration int x; int y; } Point; // Data Type Point
We can now declare "structure variables" of type Point, such as the following:
Point p1, p2, p3; // Define Structure Variables
Notice how much shorter and neater this is compared to the following:
struct Point p1, p2, p3; // Define Structure Variables
Since there is hardly any reason to use the "struct Point" form, we could omit Point from the previous declaration and write this:
typedef struct { // Structure Datatype Declaration int x; int y; } Point; // Data Type Name
Structure in Memory
Consider the following statements:
typedef struct { // Structure Datatype Declaration int x; int y; } Point; // Datatype Name Point p1; // Define Structure Variable
When a structure variable, p1, is declared, the definition reserves enough memory spaces to hold all the members of p1 — namely x and y. In this case, there will be 4 bytes for each of the two ints. Figure 9.1 shows how p1, p2, and p3 look in memory.
Figure 9.1: Structure Members in Memory
Structure for Date
A date consists of three parts: the year, the month, and the day. Each of these parts can be represented by an integer. For example, the "March 4th, 2005" can be represented by the year, 2006; the month, 4; and the day 4.
typedef struct { // Structure Declaration int year; int month; int day; } Date;
9.2 Accessing Structure Members and Array of Structures
There are two types of operators used for accessing members of a structure:
- Dot Operator . — Direct accessing structure members of a structure variable
- Indirection Operator * — Indirect accessing structure members through a structure pointer
- Arrow Operator -> — Indirect accessing structure members through a structure pointer
- Dot Operator ( . ) — Direct Accessing
- Indirection ( * ) and Arrow Operator ( -> ) — Indirect Accessing
- Dot Operator ( . ) — Direct Accessing
- Indirection ( * ) and Arrow Operator ( -> ) — Indirect Accessing
Dot Operator ( . ) — Direct Accessing
The dot (.) operator is used to access structure members of a structure variable. Here is how that looks:
typedef struct { // Structure Declaration int x; int y; } Point; // Data Type: Parts int main(){ Point p1, p2, p3; // Structure Variables: p1, p2, and p3 p2.x = 12; p2.y = 25; ... }
Once a structure variable has been defined, its members can be accessed using the dot operator. Line 10 is how the second member is given a value.
p2.y = 25;
The structure member is written in three parts:
- The name of the structure variable (p2)
- The dot operator, which consists of a period (,)
- The member name (y)
This means "the y member of p2."
The variable name must be used to distinguish one variable from another when there is more than one, such as p1, p2, p3, and so on, as shown in Figure 9.2.
Figure 9.2: The Dot Operator
The structure members are treated just like other variables. In the statement p2.y = 25;, the member is given the value 25 using a normal assignment operator. The program also shows members using in cout or printf statements such as:
cout << "x vale of p2 = " << p2.x << endl; printf("y value of p2 = %d \n", p2.y);
These statements output the values of the structure members.
Indirection ( * ) and Arrow Operator ( -> ) — Indirect Accessing
Structure Pointer: Defined as the pointer which points to the address of the memory block that stores a structure is known as the structure pointer.
Syntax of Indirection Operator (*) with Dot Operator (.)
(* pointer_variable) . structure_member = value;
Indirectly access any of the members of the structure pointed to by the pointer variable.
The parentheses are required because the dot operator (.) has higher precedence than the indirection operator (*).
The -> is called the arrow operator. It is formed by using the minus sign followed by a greater than sign. Simply saying: To access members of a structure, use the dot operator. To access members of a structure through a pointer, use the arrow operator.
Syntax of Arrow Operator (->)
pointer_variable -> structure_member = value;
The operator is used along with a pointer variable. It will assign the value at the variable to which the pointer points.
For example, the following is the declaration for a pointer to structure:
typedef struct Point { // Structure Datatype Declaration int x; int y; int z; } Point; // Datatype Name Point p1; // Define Structure Variable Point *ptr; // Define Structure Pointer ptr = &p1; p1.x = 10; (*ptr).y = 20; ptr->z = 30;
- Line 1~5: Define a structure data type named Point
- Line 7: Declared a structure variable to be of type Point.
- Line 8: Declared a variable to be a pointer to a structure Point variable
- Line 10: Take the address of the structure variable p1 and assigns it to a structure pointer named ptr
- Line 11: p1 is not a pointer, so the dot operator is the correct member selection operator
- Line 12: Use the indirect accessing operator to access the member of the Point structure pointed by ptr.
- Line 13: Use the arrow operator to access the members of the structure that a pointer variable points to.
9.4 Bit-Fields in Structure
Bit Fields allow the packing of data in a structure. This is especially useful when memory or data storage is at a premium. Typical examples include −
Packing several objects into a machine word. e.g. 1 bit flags can be compacted.
Reading external file formats -- non-standard file formats could be read in, e.g., 9-bit integers.
C allows us to do this in a structure definition by putting :bit length after the variable. For example −
struct packed_struct {
unsigned int f1:1;
unsigned int f2:1;
unsigned int f3:1;
unsigned int f4:1;
unsigned int type:4;
unsigned int my_int:9;
} pack;
Here, the packed_struct contains 6 members: Four 1-bit flags f1..f3, a 4-bit type, and a 9-bit my_int.
C automatically packs the above bit fields as compactly as possible, provided that the maximum length of the field is less than or equal to the integer word length of the computer. If this is not the case, then some compilers may allow memory overlap for the fields while others would store the next field in the next word.
9.6 Nested Structures
Nested Structure in C: Struct inside another struct
You can use a structure inside another structure, which is fairly possible. As I explained above that once you declared a structure, the struct struct_name acts as a new data type so you can include it in another struct just like the data type of other data members. Sounds confusing? Don’t worry. The following example will clear your doubt.