c

examples

examples.cšŸ”§
/**
 * Unions in C - Examples
 * 
 * This file demonstrates the use of unions for memory sharing,
 * type punning, and variant data types.
 * 
 * Compile: gcc examples.c -o examples
 * Run: ./examples
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

/* ============================================================
 * EXAMPLE 1: Basic Union Declaration and Usage
 * ============================================================ */

union Number {
    int integer;
    float decimal;
    char character;
};

void example1_basic_union(void) {
    printf("=== EXAMPLE 1: Basic Union ===\n\n");
    
    union Number num;
    
    printf("Size of union Number: %zu bytes\n\n", sizeof(union Number));
    
    // Use as integer
    num.integer = 42;
    printf("After num.integer = 42:\n");
    printf("  num.integer = %d\n", num.integer);
    printf("  num.decimal = %f (garbage)\n", num.decimal);
    printf("  num.character = '%c' (ASCII %d)\n\n", 
           num.character, (unsigned char)num.character);
    
    // Use as float
    num.decimal = 3.14f;
    printf("After num.decimal = 3.14:\n");
    printf("  num.integer = %d (garbage)\n", num.integer);
    printf("  num.decimal = %f\n", num.decimal);
    printf("  num.character = '%c' (garbage)\n\n", num.character);
    
    // Use as character
    num.character = 'A';
    printf("After num.character = 'A':\n");
    printf("  num.integer = %d (mostly 'A')\n", num.integer);
    printf("  num.decimal = %f (garbage)\n", num.decimal);
    printf("  num.character = '%c'\n", num.character);
}


/* ============================================================
 * EXAMPLE 2: Memory Sharing Demonstration
 * ============================================================ */

void example2_memory_sharing(void) {
    printf("\n=== EXAMPLE 2: Memory Sharing ===\n\n");
    
    union Number num;
    
    // All members have same address
    printf("Address comparison:\n");
    printf("  &num          = %p\n", (void*)&num);
    printf("  &num.integer  = %p\n", (void*)&num.integer);
    printf("  &num.decimal  = %p\n", (void*)&num.decimal);
    printf("  &num.character = %p\n", (void*)&num.character);
    printf("\nAll addresses are the same!\n");
}


/* ============================================================
 * EXAMPLE 3: Union vs Structure Size
 * ============================================================ */

struct DataStruct {
    char c;
    int i;
    double d;
};

union DataUnion {
    char c;
    int i;
    double d;
};

void example3_size_comparison(void) {
    printf("\n=== EXAMPLE 3: Union vs Structure Size ===\n\n");
    
    printf("Member sizes:\n");
    printf("  char: %zu byte\n", sizeof(char));
    printf("  int: %zu bytes\n", sizeof(int));
    printf("  double: %zu bytes\n\n", sizeof(double));
    
    printf("Aggregate sizes:\n");
    printf("  struct DataStruct: %zu bytes\n", sizeof(struct DataStruct));
    printf("  union DataUnion: %zu bytes\n\n", sizeof(union DataUnion));
    
    printf("Structure = sum of members + padding\n");
    printf("Union = size of largest member (double = 8 bytes)\n");
}


/* ============================================================
 * EXAMPLE 4: Type Punning - Viewing Data as Different Types
 * ============================================================ */

void example4_type_punning(void) {
    printf("\n=== EXAMPLE 4: Type Punning ===\n\n");
    
    // View float as its bit representation
    union FloatBits {
        float f;
        uint32_t bits;
        uint8_t bytes[4];
    };
    
    union FloatBits fb;
    
    printf("Examining IEEE 754 representation:\n\n");
    
    // Test with 1.0f
    fb.f = 1.0f;
    printf("Float 1.0:\n");
    printf("  Hex bits: 0x%08X\n", fb.bits);
    printf("  Bytes: ");
    for (int i = 3; i >= 0; i--) {
        printf("%02X ", fb.bytes[i]);
    }
    printf("\n\n");
    
    // Test with -2.0f
    fb.f = -2.0f;
    printf("Float -2.0:\n");
    printf("  Hex bits: 0x%08X\n", fb.bits);
    printf("  Sign bit: %d (negative)\n", (fb.bits >> 31) & 1);
    printf("\n");
    
    // Test with 0.0f
    fb.f = 0.0f;
    printf("Float 0.0:\n");
    printf("  Hex bits: 0x%08X\n", fb.bits);
}


/* ============================================================
 * EXAMPLE 5: IP Address Manipulation
 * ============================================================ */

void example5_ip_address(void) {
    printf("\n=== EXAMPLE 5: IP Address Manipulation ===\n\n");
    
    union IPAddress {
        uint32_t address;
        uint8_t octets[4];
    };
    
    union IPAddress ip;
    
    // Set individual octets
    ip.octets[0] = 192;
    ip.octets[1] = 168;
    ip.octets[2] = 1;
    ip.octets[3] = 100;
    
    printf("Setting IP as octets:\n");
    printf("  Octets: %d.%d.%d.%d\n", 
           ip.octets[0], ip.octets[1], 
           ip.octets[2], ip.octets[3]);
    printf("  As 32-bit value: 0x%08X\n\n", ip.address);
    
    // Set as 32-bit value (note: byte order matters!)
    ip.address = 0x0A000001;  // 10.0.0.1 in network byte order
    printf("Setting IP as 32-bit (0x0A000001):\n");
    printf("  Octets: %d.%d.%d.%d\n", 
           ip.octets[0], ip.octets[1], 
           ip.octets[2], ip.octets[3]);
    printf("  (Result depends on endianness)\n");
}


/* ============================================================
 * EXAMPLE 6: Tagged Union (Safe Variant Type)
 * ============================================================ */

enum ValueType {
    VAL_INT,
    VAL_FLOAT,
    VAL_STRING
};

struct Variant {
    enum ValueType type;
    union {
        int intVal;
        float floatVal;
        char strVal[32];
    } data;
};

void printVariant(const struct Variant *v) {
    printf("  ");
    switch (v->type) {
        case VAL_INT:
            printf("Integer: %d\n", v->data.intVal);
            break;
        case VAL_FLOAT:
            printf("Float: %.2f\n", v->data.floatVal);
            break;
        case VAL_STRING:
            printf("String: \"%s\"\n", v->data.strVal);
            break;
    }
}

void example6_tagged_union(void) {
    printf("\n=== EXAMPLE 6: Tagged Union ===\n\n");
    
    struct Variant values[4];
    
    // Integer value
    values[0].type = VAL_INT;
    values[0].data.intVal = 42;
    
    // Float value
    values[1].type = VAL_FLOAT;
    values[1].data.floatVal = 3.14f;
    
    // String value
    values[2].type = VAL_STRING;
    strcpy(values[2].data.strVal, "Hello, World!");
    
    // Another integer
    values[3].type = VAL_INT;
    values[3].data.intVal = -100;
    
    printf("Array of variants:\n");
    for (int i = 0; i < 4; i++) {
        printVariant(&values[i]);
    }
}


/* ============================================================
 * EXAMPLE 7: Hardware Register Simulation
 * ============================================================ */

void example7_hardware_register(void) {
    printf("\n=== EXAMPLE 7: Hardware Register Simulation ===\n\n");
    
    union StatusRegister {
        uint8_t value;
        struct {
            uint8_t ready    : 1;
            uint8_t busy     : 1;
            uint8_t error    : 1;
            uint8_t overflow : 1;
            uint8_t underrun : 1;
            uint8_t reserved : 3;
        } flags;
    };
    
    union StatusRegister status;
    
    // Set individual flags
    status.value = 0;
    status.flags.ready = 1;
    status.flags.busy = 0;
    status.flags.error = 0;
    
    printf("Setting flags individually:\n");
    printf("  ready=%d, busy=%d, error=%d\n",
           status.flags.ready, status.flags.busy, status.flags.error);
    printf("  Raw value: 0x%02X\n\n", status.value);
    
    // Set raw value and read flags
    status.value = 0x07;  // Binary: 00000111
    printf("Setting raw value to 0x07:\n");
    printf("  ready=%d, busy=%d, error=%d\n",
           status.flags.ready, status.flags.busy, status.flags.error);
    printf("  overflow=%d, underrun=%d\n",
           status.flags.overflow, status.flags.underrun);
}


/* ============================================================
 * EXAMPLE 8: Union in Structure (Message Protocol)
 * ============================================================ */

enum MessageType {
    MSG_TEXT,
    MSG_NUMBER,
    MSG_COORDS
};

struct Message {
    enum MessageType type;
    int id;
    union {
        char text[64];
        int number;
        struct { int x, y; } coords;
    } payload;
};

void processMessage(const struct Message *msg) {
    printf("  Message ID: %d\n", msg->id);
    
    switch (msg->type) {
        case MSG_TEXT:
            printf("  Type: TEXT\n");
            printf("  Content: \"%s\"\n", msg->payload.text);
            break;
        case MSG_NUMBER:
            printf("  Type: NUMBER\n");
            printf("  Value: %d\n", msg->payload.number);
            break;
        case MSG_COORDS:
            printf("  Type: COORDS\n");
            printf("  Position: (%d, %d)\n", 
                   msg->payload.coords.x, msg->payload.coords.y);
            break;
    }
}

void example8_message_protocol(void) {
    printf("\n=== EXAMPLE 8: Message Protocol ===\n\n");
    
    struct Message messages[3];
    
    // Text message
    messages[0].type = MSG_TEXT;
    messages[0].id = 1;
    strcpy(messages[0].payload.text, "Hello from sender");
    
    // Number message
    messages[1].type = MSG_NUMBER;
    messages[1].id = 2;
    messages[1].payload.number = 12345;
    
    // Coordinates message
    messages[2].type = MSG_COORDS;
    messages[2].id = 3;
    messages[2].payload.coords.x = 100;
    messages[2].payload.coords.y = 200;
    
    printf("Processing messages:\n\n");
    for (int i = 0; i < 3; i++) {
        processMessage(&messages[i]);
        printf("\n");
    }
}


/* ============================================================
 * EXAMPLE 9: Anonymous Union (C11)
 * ============================================================ */

struct Shape {
    enum { CIRCLE, RECTANGLE, TRIANGLE } type;
    
    union {  // Anonymous union
        struct { float radius; } circle;
        struct { float width, height; } rectangle;
        struct { float base, altitude; } triangle;
    };  // No name - direct access
};

float calculateArea(const struct Shape *s) {
    switch (s->type) {
        case CIRCLE:
            return 3.14159f * s->circle.radius * s->circle.radius;
        case RECTANGLE:
            return s->rectangle.width * s->rectangle.height;
        case TRIANGLE:
            return 0.5f * s->triangle.base * s->triangle.altitude;
        default:
            return 0;
    }
}

void example9_anonymous_union(void) {
    printf("\n=== EXAMPLE 9: Anonymous Union (C11) ===\n\n");
    
    struct Shape shapes[3];
    
    // Circle
    shapes[0].type = CIRCLE;
    shapes[0].circle.radius = 5.0f;
    
    // Rectangle
    shapes[1].type = RECTANGLE;
    shapes[1].rectangle.width = 4.0f;
    shapes[1].rectangle.height = 6.0f;
    
    // Triangle
    shapes[2].type = TRIANGLE;
    shapes[2].triangle.base = 8.0f;
    shapes[2].triangle.altitude = 3.0f;
    
    const char *names[] = {"Circle", "Rectangle", "Triangle"};
    
    printf("Shape areas:\n");
    for (int i = 0; i < 3; i++) {
        printf("  %s: %.2f sq units\n", 
               names[shapes[i].type], calculateArea(&shapes[i]));
    }
}


/* ============================================================
 * EXAMPLE 10: Endianness Detection
 * ============================================================ */

void example10_endianness(void) {
    printf("\n=== EXAMPLE 10: Endianness Detection ===\n\n");
    
    union {
        uint32_t word;
        uint8_t bytes[4];
    } test;
    
    test.word = 0x01020304;
    
    printf("Testing with 0x01020304:\n");
    printf("  bytes[0] = 0x%02X\n", test.bytes[0]);
    printf("  bytes[1] = 0x%02X\n", test.bytes[1]);
    printf("  bytes[2] = 0x%02X\n", test.bytes[2]);
    printf("  bytes[3] = 0x%02X\n\n", test.bytes[3]);
    
    if (test.bytes[0] == 0x04) {
        printf("This system is LITTLE-ENDIAN\n");
        printf("(Least significant byte stored first)\n");
    } else if (test.bytes[0] == 0x01) {
        printf("This system is BIG-ENDIAN\n");
        printf("(Most significant byte stored first)\n");
    } else {
        printf("Unknown endianness\n");
    }
}


/* ============================================================
 * EXAMPLE 11: Color Representation
 * ============================================================ */

void example11_color(void) {
    printf("\n=== EXAMPLE 11: Color Representation ===\n\n");
    
    union Color {
        uint32_t rgba;
        struct {
            uint8_t r;
            uint8_t g;
            uint8_t b;
            uint8_t a;
        } channels;
        uint8_t bytes[4];
    };
    
    union Color color;
    
    // Set as individual channels
    color.channels.r = 255;
    color.channels.g = 128;
    color.channels.b = 64;
    color.channels.a = 255;
    
    printf("Setting color as RGBA(255, 128, 64, 255):\n");
    printf("  As hex: 0x%08X\n", color.rgba);
    printf("  R=%d, G=%d, B=%d, A=%d\n\n",
           color.channels.r, color.channels.g,
           color.channels.b, color.channels.a);
    
    // Set as hex value
    color.rgba = 0xFF00FF80;  // Magenta with 50% alpha
    printf("Setting color as 0xFF00FF80:\n");
    printf("  R=%d, G=%d, B=%d, A=%d\n",
           color.channels.r, color.channels.g,
           color.channels.b, color.channels.a);
}


/* ============================================================
 * EXAMPLE 12: Dynamic Union Array
 * ============================================================ */

void example12_dynamic_array(void) {
    printf("\n=== EXAMPLE 12: Dynamic Union Array ===\n\n");
    
    union DataUnion *array = malloc(5 * sizeof(union DataUnion));
    
    if (array == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    
    // Store different types (be careful: only one type per element is valid)
    for (int i = 0; i < 5; i++) {
        if (i % 2 == 0) {
            array[i].i = i * 100;
        } else {
            array[i].d = i * 1.5;
        }
    }
    
    printf("Note: Each element stores ONE type at a time.\n");
    printf("Even indices (int): ");
    for (int i = 0; i < 5; i += 2) {
        printf("%d ", array[i].i);
    }
    printf("\nOdd indices (double): ");
    for (int i = 1; i < 5; i += 2) {
        printf("%.1f ", array[i].d);
    }
    printf("\n");
    
    free(array);
}


/* ============================================================
 * MAIN FUNCTION
 * ============================================================ */

int main() {
    printf("╔════════════════════════════════════════════════════════╗\n");
    printf("ā•‘              UNIONS IN C - EXAMPLES                    ā•‘\n");
    printf("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n\n");
    
    example1_basic_union();
    example2_memory_sharing();
    example3_size_comparison();
    example4_type_punning();
    example5_ip_address();
    example6_tagged_union();
    example7_hardware_register();
    example8_message_protocol();
    example9_anonymous_union();
    example10_endianness();
    example11_color();
    example12_dynamic_array();
    
    printf("\n═══════════════════════════════════════════════════════\n");
    printf("All examples completed successfully!\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML