Unions
Understanding unions and how they differ from structures. Using unions to save memory.
Tagged Unions in C
Introduction
This lesson explores the concept of tagged unions (also known as discriminated unions), where a separate member is used to indicate the type of data currently stored in the union. It discusses the advantages of tagged unions for type safety and code clarity. Example applications, such as handling different data formats, will be provided.
Union Use Cases
Unions are useful when you need to store different types of data in the same memory location, but only one type at a time. They are often used to save memory or to represent data that can have multiple interpretations. Here are some common use cases:
- Representing data with variant types (e.g., a number that can be an integer or a floating-point number).
- Interpreting a block of memory in different ways (e.g., reading a network packet as different structures depending on its type).
- Creating data structures that can hold one of several possible values.
Tagged Unions (Discriminated Unions)
A tagged union is a union combined with a tag (usually an enum) that indicates which member of the union is currently active. This helps ensure type safety and prevents accidental access of the wrong data type. Without a tag, you could easily misinterpret the data stored in the union, leading to unexpected and potentially disastrous results.
The tag allows you to write code that checks the current data type before accessing the union, ensuring that you are working with the correct data.
Example: Handling Different Data Formats
Imagine you are writing a program that needs to process data from different file formats. Each format might contain different types of data. You can use a tagged union to represent the data from any of these formats.
#include <stdio.h>
typedef enum {
INT_TYPE,
FLOAT_TYPE,
STRING_TYPE
} DataType;
typedef struct {
DataType type;
union {
int intValue;
float floatValue;
char stringValue[20];
} data;
} Variant;
void printVariant(Variant v) {
switch (v.type) {
case INT_TYPE:
printf("Integer: %d\n", v.data.intValue);
break;
case FLOAT_TYPE:
printf("Float: %f\n", v.data.floatValue);
break;
case STRING_TYPE:
printf("String: %s\n", v.data.stringValue);
break;
default:
printf("Unknown data type\n");
}
}
int main() {
Variant myVar;
// Store an integer
myVar.type = INT_TYPE;
myVar.data.intValue = 10;
printVariant(myVar);
// Store a float
myVar.type = FLOAT_TYPE;
myVar.data.floatValue = 3.14;
printVariant(myVar);
// Store a string
myVar.type = STRING_TYPE;
strcpy(myVar.data.stringValue, "Hello");
printVariant(myVar);
return 0;
}
Explanation:
- The
DataType
enum defines the possible types that the union can hold. - The
Variant
struct contains aDataType
tag and a union calleddata
. - The
printVariant
function uses aswitch
statement to determine the correct way to print the data based on thetype
tag.
Advantages of Tagged Unions
- Type Safety: The tag ensures that you only access the data in the union as the type it was last assigned as. This prevents type errors and undefined behavior.
- Code Clarity: The tag makes it clear which type of data is currently stored in the union, making the code easier to understand and maintain.
- Error Prevention: By using a switch statement based on the tag, you can handle different data types in a controlled manner, reducing the risk of errors.