Why do structures exist in C.

13.3. Structures

If a series of related data is to be processed, arrays and pointers prove to be suitable. Both are subject to the restriction that all elements must be of the same data type. In the case of many problems, however, the necessity arises that data of different types have to find space within a composite data object.

A typical example of this are the data records for an address management system. Each entry must be able to contain at least the surname and first name of the person concerned (generally as arrays of the char type) and their telephone number and zip code (as whole numbers). It is desirable that you can access individual data in the same way as you can access the data record as a whole, for example to write it to a file.

For this purpose, C offers you the structure with which you can combine a conglomerate of different data types into one data object and access each individual element.

Declaration of structures

Since arrays only have elements of the same data type, all arrays of a certain data type differ only in the number of their elements. You announce this at the definition, so that the compiler has all information about the structure of a certain array from this point in time. The situation is different with structures: Since each structure can be completely unique, you must inform the compiler about its composition before using a structure. This is done in the form of a declaration that provides a template for the structure in question. Only then can you define variables of their type.

The declaration of a structure must be made using the reserved word struct and has the general form:

A structure can contain elements of any data type, including types defined with typedef, enumeration types or even structures. As with the enumeration types, either the name or the variable list can be missing when declaring structures. If you do not specify the structure name, you make a so-called "anonymous declaration". In this case, only those variables are available that you define in the declaration by specifying them in the variable list. Subsequent definitions of variables of this type are not possible, since they can no longer refer to this structure due to a lack of names. Example:

As expected, after this declaration you have two variables available, both of which are of the type of the specified structure. This kind of declaration of structures is rather unusual and rarely found. The variant in which no variables are defined and the structure name is available is more common. The initial lack of variables is not a problem, as any number of them can be defined afterwards. The above example would look like this in this variant:

Only when defining a variable of the type struct address does the compiler reserve sufficient space to accommodate all the elements of the structure. In our case, the reserved space is at least 2 * 30 * sizeof (char) + 2 * sizeof (unsigned long) bytes. In fact, the memory requirement is usually greater than the added up sizes of all elements, since the compiler aligns the beginning of the individual elements with favorable memory addresses (e.g. even addresses) depending on the system. Therefore, if you request space for a structure with a function for dynamic memory management, then you should definitely use the sizeof operator to determine its actual space requirements! The size of the structure address can therefore be determined using sizeof (struct address).

It is convenient, and therefore widespread, to introduce the type of structures by using typedef under a name of your own. This eliminates the need to specify the keyword struct when defining variables or when using sizeof. To make the structure address available as the data type Address, you would have to use the instruction

insert. There is a short form of structures for assigning names using typedef, which allows typdef to be used when declaring them:

This declaration does not even stop at assigning a name to the structure, but instead makes it available as the data type Address thanks to typedef. Variables of the ADDRESS type are of course not yet available after this declaration, but they can later be quite simply in the form

To be defined.

Scope of structures

In principle, the same rules apply to the scope and "lifetime" of structures as to simple variables. The matter is quite simple when variables are defined in the course of the structure declaration. Depending on the location of the declaration, the variables are then available globally, within a function or within an instruction block. However, if - as is usually the case - the declaration of a structure and the definition of the variables take place separately, a distinction must be made between the availability of the structure as a data type and the scope of individual variables. If you declare a structure before main (), i.e. globally, this means that the "template" of this structure is known in all functions and therefore variables of this type can be defined everywhere:

It looks different as soon as a structure is declared within a function. Then it is only available locally as a data type and variables can only be defined there:

Initialization of structures

Individual elements cannot be initialized within the framework of a structure declaration, since no memory space is reserved during this process and it is therefore unclear where the initial values ​​should be saved. In addition, several variables can be defined in the course of the declaration so that it cannot be determined which variable the values ​​are to be assigned to. This example shows an illegal initialization:

The correct procedure only assigns values ​​to the individual elements when the variables are defined; this is done analogously to the initialization of arrays:

Structure assignments

The assignment of values ​​using the assignment operator is limited to simple variables, because arrays in this form cannot accept series of data. Instead, the values ​​for the individual elements must be assigned separately, either using your own code or using library functions (mainly for strings).

Surprisingly, with the even more complex data type, the structure, C allows the direct assignment of all values ​​contained in it to a structure of the same type. This works even if a structure contains arrays and pointers! The following structure is available under the name Address:

If two variables of the type Address are now defined,

then the entire content from supplier can go through

assigned to customer. The call

As expected, has the result "Peter Fischer".

Access to individual elements

So that the individual elements of a structure can be used e.g. within expressions or passed as arguments to functions, they must be specifically addressable. The name of an element consists of the name of the structure and its own variable name; both components are separated by the point operator.

For example, the variable Supplier of the type ADDRESS is defined. Then the value for the phone number can be assigned as follows:

It is obvious that only operations with an element are permitted that would also be possible with a single variable of this type. A character string cannot be stored in a character array within a structure by means of assignment any more than would be possible with an "ordinary" array. In both cases you need a str .. () or mem ... () function. In the case of our variable supplier, we have to save the name "Meier" e.g. as follows in the szName array:

Since an "ordinary", uninitialized pointer represents a wild pointer, you can be sure that such a pointer is present even if it is an element of a structure. In the interests of functional programs, you should therefore refrain from assigning data to a wild pointer. We assume that the structure address used so far is defined as follows:

Then it goes without saying in this case that data for surname and first name can only be saved if the necessary memory has been requested beforehand, that is

Because arrays are composite data types, they provide a mechanism by which their elements can be accessed. As you know, this is the index that must be specified after the array name. If an array is located within a structure, addressing an array element requires two pieces of information: one stating that the array is an element of a structure, and a second, which must refer to an element of the array in the form of an index. In order to set the first letter of the first name in the structure address to 'X', the following assignment must be made:

The same applies, of course, to pointers if they are to be dereferenced with the help of an index:

Arrays of structures

In principle, arrays with all valid data types are permitted in C, and accordingly also with structures. The condition is of course that a valid declaration of the structure is available before an array of this data type can be defined. Assuming that an address management system should be able to hold up to 100 entries in the memory, the following array is recommended - based on our address structure:

If a certain element of this array is to be addressed, this can be done in the usual manner (customers [0] to customers [99]). However, if you also want to use an element of a structure, the structure name must contain an index. However, while the first letter of the szName string in the Supplier structure is designated with Supplier.szName [0], you get to the telephone number of the first customer with Customer [0] .ulTel. The name component in front of the dot operator stands for the structure: If structures are elements of an array, then the index belongs to the name and must therefore appear in the first part for the variable name. The opposite is true for arrays in structures: There the index is part of the variable that is an element of the structure:

Pointers to structures

Pointers to structures are particularly often used as arguments for function calls. If you simply pass structures to a function, it is well known that a "call by value" occurs, in which the called function cannot change the argument values ​​of the caller because it is known to contain a copy. In contrast to this, a pointer to a structure causes a "call by reference".

The definition of a pointer to a structure follows the usual pattern. In the following, the structure address is declared again, then generated

a pointer to a structure of the address type. The memory address of a structure can be assigned as usual with the help of the address operator, e.g.

Up to this point, pointers to structures do not differ from those to other data types. Special features must be taken into account when accessing the elements of a structure via pointers. If a value for the telephone number is to be assigned with the pointer pAdresse defined above, this can be done in the following form:

This method is correct, although unusual. Since elements of structures are very often accessed with the help of pointers, there is a separate operator for this purpose, the arrow operator (it is made up of a '-' and a '>'). Instead of the formulation chosen above, a typical C programmer would choose the following variant:

If the arrow operator is used, the content operator is not required.

The next example program makes extensive use of pointers to structures. It implements a word counting function that outputs all the words in the input stream in alphabetical order and provides information on the number of occurrences. The use of binary trees and recursive data types actually goes beyond the possibilities of basic knowledge and is no longer explained here. Therefore, this example should be understood more as an outlook on the possibilities of advanced C programming. Nevertheless, all linguistic constructions can be understood after reading it so far. The interested reader therefore has the opportunity to understand how the program works with detailed employment.