While an array is useful for grouping homogeneous data items that are of the same data type, a record (struct in C/C++) is used for grouping heterogeneous data items, which may be of the same or different data types. For example, an array is probably better for storing a list of test scores in a program that works with the \(i^{th}\) test score, but a struct might be better for storing the coordinates of a point on an \(x - y\) graph.
The data elements in a struct are usually called fields. Accessing a field in a struct also requires two address-related items:
The first thing we do is to define a new struct data type:
struct aTag { /* Define new struct type */
char aByte;
int anInt;
char anotherByte;
};
The tag name is a C identifier created by the programmer. Since this is a nonsense program, we have simply used aTag. Once a tag has been defined, we create variables of this new data type in the usual way:
struct aTag x;
struct aTag y;
The tag name is not required, but then you would have to define the fields for each struct variable:
struct {
char aByte;
int anInt;
char anotherByte;
} x;
struct {
char aByte;
int anInt;
char anotherByte;
} y;
This is entirely equivalent to the use of the tag, but it greatly increases the chances of making an error. Also, as you will see in the following sections, defining a tag is necessary for passing a struct as an argument to a function.
Assignment to each of the three fields in the “x” struct is accomplished by giving the name of the struct variable, followed by a dot (.), followed by the name of the field:
We can see that the compiler adds the (negative) offset of each field in each struct to the address in the frame pointer to access the respective field. For example, x.aByte = 'a'; is implemented with:
mov r3, #97
strb r3, [fp, #-16]
You can see the relative offsets in the pictorial view of the stack frame in Figure 15.3.3 for the program in Listing 15.3.1. The offset for each field in each struct is relative to the fp. Shaded areas represent unused memory.
I take a somewhat different approach to accessing the fields of each struct in my assembly language solution, Listing 15.3.4.
Instead of computing the address of each field, I use a register to point to the beginning of the struct. Then I can simply use the offset of each field, relative to this pointer, to access the field:
Using the address of a struct can be useful if it is large. Then its address is often used in an array of structs or passing a struct as an argument to a function.