How to access items inside nested structs that contain a union in C

1 Answer

0 votes
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

// 1. Define the discriminator (tag) to track the active union state
typedef enum {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE
} ShapeType;

// 2. Define nested specific structs
typedef struct {
    float radius;
} Circle;

typedef struct {
    float width;
    float height;
} Rectangle;

// 3. Define the main container struct with nested metadata and a union
typedef struct {
    int id;
    ShapeType type; // The tag that dictates which union member is valid
    
    // Nested standard struct for metadata
    struct {
        char name[32];
        bool is_active;
    } metadata;

    // Nested union for mutually exclusive variant data
    union {
        Circle circle;
        Rectangle rectangle;
    } dimensions;
} Shape;

/**
 * @brief Safely accesses and prints items from nested structs and unions.
 * @Pointer to the Shape structure being inspected.
 */
void print_shape_properties(const Shape *shape) {
    // Best practice: Always validate pointer inputs
    if (shape == NULL) {
        printf("Error: Received NULL shape pointer.\n");
        return;
    }

    // Accessing nested struct fields using the arrow operator (->)
    printf("Shape ID: %d\n", shape->id);
    printf("Shape Name: %s\n", shape->metadata.name);
    printf("Status: %s\n", shape->metadata.is_active ? "Active" : "Inactive");

    // Switch on the discriminator (tag) to safely access the correct union member
    switch (shape->type) {
        case SHAPE_CIRCLE:
            // Accessing union member: shape->dimensions.circle.radius
            printf("Type: Circle\n");
            printf("Radius: %.2f\n", shape->dimensions.circle.radius);
            break;

        case SHAPE_RECTANGLE:
            // Accessing union member: shape->dimensions.rectangle.width / height
            printf("Type: Rectangle\n");
            printf("Width: %.2f, Height: %.2f\n", 
                   shape->dimensions.rectangle.width, 
                   shape->dimensions.rectangle.height);
            break;

        default:
            printf("Warning: Unknown shape type encountered.\n");
            break;
    }
    printf("------------------------------------\n");
}

int main(void) {
    // Initialize a Circle shape
    Shape my_circle = {
        .id = 101,
        .type = SHAPE_CIRCLE,
        .metadata = {
            .name = "Unit Circle",
            .is_active = true
        },
        .dimensions = {
            .circle = { .radius = 5.5f }
        }
    };

    // Initialize a Rectangle shape
    Shape my_rectangle = {
        .id = 102,
        .type = SHAPE_RECTANGLE,
        .metadata = {
            .name = "Bounding Box",
            .is_active = false
        },
        .dimensions = {
            .rectangle = { .width = 10.0f, .height = 20.0f }
        }
    };

    // Access and print using our safe function
    print_shape_properties(&my_circle);
    print_shape_properties(&my_rectangle);

    return 0;
}


/*
run:

Shape ID: 101
Shape Name: Unit Circle
Status: Active
Type: Circle
Radius: 5.50
------------------------------------
Shape ID: 102
Shape Name: Bounding Box
Status: Inactive
Type: Rectangle
Width: 10.00, Height: 20.00
------------------------------------

*/

 



answered 7 hours ago by avibootz

Related questions

...