Programming: Structs

Imagine we would like to draw a circle on display. The drawing tools in the graphics library for drawing a circle require three parameters: an x-coordinate for the circle’s center, a corresponding y-coordinate, and the radius of the circle. It sounds simple enough. We can just put those values into the function and get the job done. However, what if we like to update the circle’s position multiple times, similar to a ball that should be controlled by moving the joystick?  For this case, it is better to declare variables to store the coordinates and radius of the circle, and then pass those variables into the circle drawing function. Now, what if we like to draw multiple circles with the same functionality? Creating three uniquely-named variables for each circle can get very cumbersome to keep track of and organize. For these purposes, structs prove to be a beneficial tool.


A struct (short for “structure”) is, in essence, a data type containing a group of other variables. Structs are useful for grouping together variables that have some shared association as if they were attributes of an object. Structs are similar to classes, but they do not have functions. Due to this difference, C is not an object-oriented language like C++. However, you can use structs (in tandem with typedef) to create “objects” that each have definable attributes. For instance, if we create a FruitBasket struct, it can have the members fruit, quantity, and price. All subsequent FruitBaskets will each have a field for the fruit contained in the basket, one for its quantity of fruit, and one for its price. The declaration for such a struct can be as follows: 

typedef struct {

    fruit_t fruit; // fruit_t is a typedef enum of fruits

    int quantity;

    double price;

} FruitBasket;

As shown above, each member of the struct must have its own data type. After all, each member is simply a variable, so the member can be anything: a primitive (like an integer), a user-defined data type (using typedef), or even a pointer. To initialize a struct, you have two options:

// Initialize each member of the struct individually

FruitBasket myBasket1; // creates a variable myBasket1, which is a FruitBasket

myBasket1.fruit = APPLE;

myBasket1.quantity = 4;

myBasket1.price = 3.99;


// Initialize all at once

FruitBasket myBasket2 = {BANANA, 5, 4.50};

Note that in the first method, each member is modified by using the accessor operator (.). This works if you have an instance of the struct initialized. When you pass a struct as a function parameter, the function creates a copy of the struct, just like any other variable passed by value. You can use a period to access members of this copy, just like with the original struct. If, however, the struct is passed by reference (a pointer), then the period no longer works. Instead, you would have to use the -> operator, which is essentially a “dereference and access” operator. As the description would imply, you would use the -> operator for pointers to structs.

void SellFruitBasket(FruitBasket *soldBasket_p, double *wallet_p) {

    // When the fruit basket is sold, the price of the basket is added to the wallet

    *wallet_p += soldBasket_p->price;


    // Functionally, this would also be equivalent:

    // *wallet_p += (*soldBasket).price;

    // … But the -> operator is usually easier to read

}


programming example

https://github.com/VT-Introduction-to-Embedded-systems/programmimng_pointers_struct.git