Skip to main content
Engineering LibreTexts

10.1: Introduction

  • Page ID
    35847
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    C allows compound data called structures, or struct for short. The idea is to use a variety of the basic data types such as float or int to describe some sort of object. Structures may contain several of each type along with pointers, arrays, and even other structures. There are many uses for such a construct and structures are very common in production C code.

    As an example, we may wish to describe an electronic component such as a transistor. What sort of things do we need? There are several performance parameters that may be used such as current gain, breakdown voltage and maximum power dissipation. All of these items may be represented as double variables. There will be a model number. This will probably be a string as it may contain letters (such as “2N3904”). There will need to be a manufacturer’s code. This could be an int. A real world device will have many more parameters than these five, but these will suffice for our purposes. If you only have one transistor to deal with, five separate variables is not a big deal to keep track of. On the other hand, what if you have a great number of parts as in a database? Perhaps there are 1000 devices. Creating 5000 separate variables and keeping them straight presents a bit of a challenge. It would be nice if we could combine the five items together into a “super variable”. Then, all we have to worry about is creating 1000 of them for the database (perhaps with an array, although there are other techniques). There shouldn’t be a problem of getting the current gain of one device confused with that of another. This is where structures come in. Below is an example of how we would define this transistor structure and associated instances.

    struct transistor {
        double        currentgain;
        double        breakdown;
        double        maxpower;
        short int     manufacturer;
        char          model[20];
    };
    
    struct transistor my_transistor;
    struct transistor *ptransistor;
    

    We have defined a structure of type transistor. We have also declared an instance of a struct transistor called my_transistor, along with a pointer to a struct transistor called ptransistor. The five elements are referred to as the fields of the structure (e.g., the currentgain field). Note that this structure contains an array of characters for the model name/number. The model cannot exceed 19 characters (19 plus terminating null yields 20 declared). It is unlikely that we’ll ever have model name/number this long, but if by chance we do, we will have to truncate it.

    To set or retrieve values from an instance, we use a period to separate the structure name from the field of interest. Here are some examples:

    my_transistor.currentgain = 200.0;
    my_transistor.maxpower = 50.0;
    my_transistor.manufacturer = 23;
    

    In the last assignment, it may be better to use a #define rather than a hard number. For example, place the following definition in a header file and then use the assignment below:

    #define MOTOROLA 23
    
    my_transistor.manufacturer = MOTOROLA;
    

    To set the model field, you could do something like this:

    strcpy( my_transistor.model, “2N3904” );
    

    Remember, strcpy() needs addresses. The double quote string literal produces this automatically. For the model field, we are using the shortcut described in earlier work. The line above is equivalent to:

    strcpy( &(my_transistor.model[0]), “2N3904” );
    

    If you need to use a field in a computation or comparison, the access is unchanged:

    if( my_transistor.breakdown > 75.0 )
        printf(“Breakdown voltage is at least 75 volts!\n”);
    

    A good question at this point is whether of not the declared order of the fields makes any difference. This depends on the compiler and target hardware. In some processors, multiple-byte variables such as long and short integers, floats and pointers must be word aligned. For example, a short int may be required to start on an even address or a float might be required to start on an address divisible by four. In such a system, a structure declared with the order of char, float, char, int will need pad bytes between some fields to ensure alignment and will take up more memory space than if the structure was organized as float, int, char, char. This is of particular importance if large arrays of structures are to be used.


    This page titled 10.1: Introduction is shared under a CC BY-NC-SA 4.0 license and was authored, remixed, and/or curated by James M. Fiore via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.