C++

Structures, Unions & Enums in C++

902
0
Structures, Unions & Enums in C++

What are Structures, Unions, and Enums?

Structures, unions, and enums are three distinct data types in C++. They are used to organize data in a way that makes it easier to manage and manipulate.

Structures

A structure is a user-defined data type that groups together variables of different data types under a single name. It is similar to a class in that it encapsulates data and functions, but it does not have any member functions. Here’s an example:

struct Person {
    string name;
    int age;
    string gender;
};
C++

In this example, we’ve defined a structure called Person that has three member variables: name, age, and gender. Each of these variables has a different data type (string and int), but they are all grouped together under the Person name.

Unions

A union is similar to a structure in that it groups together variables of different data types under a single name. However, a union only allocates enough memory to store the largest member variable, and all member variables share the same memory location. Here’s an example:

union Number {
    int i;
    float f;
    double d;
};
C++

In this example, we’ve defined a union called Number that has three member variables: i (an integer), f (a float), and d (a double). However, because double is the largest data type, the union will only allocate enough memory to store a double. This means that if we set the value of i, the values of f and d will also be affected.

Enums

An enum is a user-defined data type that assigns names to integral constants. It is often used to represent sets of related constants, such as the days of the week or the months of the year. Here’s an example:

enum DaysOfWeek {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};
C++

In this example, we’ve defined an enum called DaysOfWeek that assigns names to the seven days of the week. Each of these names corresponds to an integral constant, with Monday being 0, Tuesday being 1, and so on.

Using Structures, Unions, and Enums

Now that we know what structures, unions, and enums are, let’s take a closer look at how we can use them in our programs.

Structures

One of the most common uses for structures is to represent real-world objects in our code. For example, we might define a structure to represent a car:

struct Car {
    string make;
    string model;
    int year;
    double price;
};
C++

With this structure, we can create instances of cars in our code:

Car myCar;
myCar.make = "Toyota";
myCar.model = "Camry";
myCar.year = 2022;
myCar.price = 24900.50;
C++

We can also define functions that take structures as arguments:

void printCar(Car car) {
    cout << car.make << " " << car.model << " (" << car.year << ") - $" << car.price << endl;
}
C++

With this function, we can call printCar and pass in our myCar instance to print out its details:

printCar(myCar);
C++

This will output:

Toyota Camry (2022) - $24900.5

We can also define arrays and pointers to structures:

Car cars[3];
cars[0] = {"Toyota", "Corolla", 2022, 19999.99};
cars[1] = {"Honda", "Civic", 2022, 21999.99};
cars[2] = {"Nissan", "Sentra", 2022, 18999.99};

Car* carPtr = &myCar;
C++

With these arrays and pointers, we can perform various operations on our structures, such as sorting them by price or printing out their details in a loop.

Unions

Unions are often used when we need to store data in different formats or data types, but we only have a limited amount of memory available. For example, we might define a union to represent a single pixel in an image:

union Pixel {
    struct {
        unsigned char r, g, b;
    } channels;
    unsigned int value;
};
C++

In this union, we have two member variables: channels, which is a structure that contains three unsigned char variables (r, g, and b), and value, which is an unsigned int. The channels structure is used to access the individual color channels of the pixel, while the value variable is used to store the pixel’s color as a single 32-bit value.

We can set the value of a pixel’s color using either the channels structure or the value variable:

Pixel p;
p.channels.r = 255;
p.channels.g = 0;
p.channels.b = 0;

// Or
p.value = 0xff0000;
C++

Both of these operations will set the pixel’s color to red.

Enums

Enums are often used to represent sets of related constants, such as the days of the week or the months of the year. We can use enums to create variables that can only take on certain values:

enum DaysOfWeek {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

DaysOfWeek today = Tuesday;
C++

In this example, we’ve defined an enum called DaysOfWeek that represents the seven days of the week. We’ve then created a variable called today and set its value to Tuesday.

We can use enums in switch statements to make our code more readable:

switch (today) {
    case Monday:
        cout << "It's Monday!" << endl;
        break;
    case Tuesday:
        cout << "It's Tuesday!" << endl;
        break;
    // And so on...
}
C++

This will output:

It's Tuesday!

Advanced Techniques

Now that we have a basic understanding of structures, unions, and enums, let’s take a look at some more advanced techniques that we can use with these data types.

Bit Fields

Bit fields are a feature of structures that allow us to specify the number of bits that each member variable should occupy. This can be useful when we need to store a large number of small values in a compact format.

struct Flags {
    unsigned int flag1 : 1;
    unsigned int flag2 : 1;
    unsigned int flag3 : 1;
    unsigned int flag4 : 1;
    unsigned int flag5 : 1;
    unsigned int reserved : 27;
};
C++

In this example, we’ve defined a structure called Flags that contains five member variables, each of which occupies a single bit. We’ve also included a reserved field that occupies the remaining 27 bits of the structure.

We can set and access the values of these bit fields using the same dot notation as we would for regular member variables:

Flags f;
f.flag1 = 1;
f.flag2 = 0;
f.flag3 = 1;
f.flag4 = 0;
f.flag5 = 1;
f.reserved = 0;

cout << f.flag1 << f.flag2 << f.flag3 << f.flag4 << f.flag5 << endl;
C++

This will output:

10101

Nested Structures

Structures can be nested inside other structures, allowing us to create complex data types that can be easily organized and manipulated.

struct Address {
    string street;
    string city;
    string state;
    string zip;
};

struct Person {
    string name;
    int age;
    Address address;
};
C++

In this example, we’ve defined a structure called Address that represents a mailing address, and a structure called Person that contains a person’s name, age, and address.

We can create and access instances of these nested structures using the same dot notation as we would for regular member variables:

Person p;
p.name = "John Smith";
p.age = 35;
p.address.street = "123 Main St";
p.address.city = "Anytown";
p.address.state = "CA";
p.address.zip = "12345";

cout << p.name << " (" << p.age << ")" << endl;
cout << p.address.street << endl;
cout << p.address.city << ", " << p.address.state << " " << p.address.zip << endl;
C++

This will output:

John Smith (35)
123 Main St
Anytown, CA 12345

Typedefs

Typedefs are a way to create aliases for existing data types, making our code more readable and easier to maintain.

typedef struct {
    int x;
    int y;
} Point;

typedef struct {
    Point topLeft;
    Point bottomRight;
} Rectangle;
C++

In this example, we’ve defined two typedefs: Point and Rectangle. Point is a structure that contains two int variables (x and y), while Rectangle is a structure that contains two Point variables (topLeft and bottomRight).

We can use these typedefs to create instances of these structures:

Rectangle r = {
    {0, 0}, // Top left
    {10, 10} // Bottom right
};
C++

We can also use these typedefs to declare variables:

Point p1 = {5, 5};
Point p2 = {10, 10};
C++

Unions with Structures

Unions can be nested inside structures, allowing us to create complex data types that can store different types of data in a compact format.

union Value {
    int intValue;
    float floatValue;
    bool boolValue;
};

struct Field {
    string name;
    char type;
    Value value;
};
C++

In this example, we’ve defined a union called Value that can store an int, float, or bool. We’ve also defined a structure called Field that contains a field name, a field type, and a Value union.

We can set the value of a field using the same dot notation as we would for regular member variables:

Field f;
f.name = "Age";
f.type = 'i';
f.value.intValue = 35;
C++

We can also access the value of a field using the same dot notation:

cout << f.name << ": ";

switch (f.type) {
    case 'i':
        cout << f.value.intValue;
        break;
    case 'f':
        cout << f.value.floatValue;
        break;
    case 'b':
        cout << (f.value.boolValue ? "true" : "false");
        break;
}

cout << endl;
C++

This will output:

Age: 35

Enums

Enums are a way to create a named set of constant values. This can make our code more readable and easier to maintain.

enum Color {
    Red,
    Green,
    Blue
};

enum Size {
    Small,
    Medium,
    Large
};
C++

In this example, we’ve defined two enums: Color and Size. Color contains three constant values (Red, Green, and Blue), while Size contains three constant values (Small, Medium, and Large).

We can use these enums to declare variables:

Color c = Green;
Size s = Medium;
C++

We can also use these enums in switch statements:

switch (c) {
    case Red:
        cout << "The color is red." << endl;
        break;
    case Green:
        cout << "The color is green." << endl;
        break;
    case Blue:
        cout << "The color is blue." << endl;
        break;
}
C++

This will output:

The color is green.

Conclusion

In conclusion, structures, unions, and enums are powerful tools that allow us to create complex data types in C++. Structures allow us to group together related data into a single entity, while unions allow us to store different types of data in a compact format. Enums allow us to create a named set of constant values that can make our code more readable and easier to maintain.

By understanding how to use these features effectively, we can create more efficient and maintainable C++ code. So, don’t hesitate to experiment with these data types and see how they can improve your code!

xalgord
WRITTEN BY

xalgord

Constantly learning & adapting to new technologies. Passionate about solving complex problems with code. #programming #softwareengineering

Leave a Reply