c
examples
examples.cš§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;
}