c
examples
examples.cš§c
/**
* Bit Fields in C - Examples
*
* This file demonstrates the use of bit fields for memory-efficient
* data storage and hardware register manipulation.
*
* Compile: gcc examples.c -o examples
* Run: ./examples
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/* ============================================================
* EXAMPLE 1: Basic Bit Field Declaration
* ============================================================ */
struct BasicFlags {
unsigned int flag1 : 1;
unsigned int flag2 : 1;
unsigned int flag3 : 1;
unsigned int flag4 : 1;
};
void example1_basic_bitfield(void) {
printf("=== EXAMPLE 1: Basic Bit Fields ===\n\n");
struct BasicFlags flags = {0};
printf("Size of struct BasicFlags: %zu bytes\n", sizeof(struct BasicFlags));
printf("(4 flags stored in %zu bytes instead of 16!)\n\n", sizeof(struct BasicFlags));
// Set individual flags
flags.flag1 = 1;
flags.flag3 = 1;
printf("After setting flag1 and flag3:\n");
printf(" flag1 = %u\n", flags.flag1);
printf(" flag2 = %u\n", flags.flag2);
printf(" flag3 = %u\n", flags.flag3);
printf(" flag4 = %u\n", flags.flag4);
}
/* ============================================================
* EXAMPLE 2: Memory Savings
* ============================================================ */
// Without bit fields
struct NormalDate {
int day; // 4 bytes
int month; // 4 bytes
int year; // 4 bytes
};
// With bit fields
struct CompactDate {
unsigned int day : 5; // 5 bits (1-31)
unsigned int month : 4; // 4 bits (1-12)
unsigned int year : 12; // 12 bits (0-4095)
};
void example2_memory_savings(void) {
printf("\n=== EXAMPLE 2: Memory Savings ===\n\n");
printf("Normal date structure:\n");
printf(" Size: %zu bytes\n\n", sizeof(struct NormalDate));
printf("Compact date structure:\n");
printf(" Size: %zu bytes\n", sizeof(struct CompactDate));
printf(" Bits used: 5 + 4 + 12 = 21 bits\n\n");
struct CompactDate date;
date.day = 25;
date.month = 12;
date.year = 2024;
printf("Stored date: %u/%u/%u\n", date.month, date.day, date.year);
printf("Memory savings: %zu bytes per date!\n",
sizeof(struct NormalDate) - sizeof(struct CompactDate));
}
/* ============================================================
* EXAMPLE 3: Multiple Bit Fields
* ============================================================ */
struct PackedData {
unsigned int type : 4; // 0-15
unsigned int subtype : 4; // 0-15
unsigned int flags : 8; // 0-255
unsigned int count : 16; // 0-65535
};
void example3_packed_data(void) {
printf("\n=== EXAMPLE 3: Packed Data ===\n\n");
struct PackedData data = {0};
printf("Size: %zu bytes for 32 bits of data\n\n", sizeof(data));
data.type = 7;
data.subtype = 3;
data.flags = 0x55;
data.count = 1000;
printf("Stored values:\n");
printf(" type = %u (4 bits)\n", data.type);
printf(" subtype = %u (4 bits)\n", data.subtype);
printf(" flags = 0x%02X (8 bits)\n", data.flags);
printf(" count = %u (16 bits)\n", data.count);
}
/* ============================================================
* EXAMPLE 4: Value Range Limits
* ============================================================ */
struct RangeLimits {
unsigned int two_bits : 2; // 0-3
unsigned int four_bits : 4; // 0-15
unsigned int eight_bits : 8; // 0-255
};
void example4_range_limits(void) {
printf("\n=== EXAMPLE 4: Value Range Limits ===\n\n");
struct RangeLimits r;
printf("Testing overflow behavior:\n\n");
// Test 2-bit field (0-3)
r.two_bits = 3;
printf("2-bit field set to 3: %u\n", r.two_bits);
r.two_bits = 5; // Overflows! 5 & 0x3 = 1
printf("2-bit field set to 5: %u (overflowed!)\n\n", r.two_bits);
// Test 4-bit field (0-15)
r.four_bits = 15;
printf("4-bit field set to 15: %u\n", r.four_bits);
r.four_bits = 20; // Overflows! 20 & 0xF = 4
printf("4-bit field set to 20: %u (overflowed!)\n\n", r.four_bits);
// Test 8-bit field (0-255)
r.eight_bits = 255;
printf("8-bit field set to 255: %u\n", r.eight_bits);
r.eight_bits = 300; // Overflows! 300 & 0xFF = 44
printf("8-bit field set to 300: %u (overflowed!)\n", r.eight_bits);
}
/* ============================================================
* EXAMPLE 5: Unnamed Bit Fields (Padding)
* ============================================================ */
struct WithPadding {
unsigned int a : 4;
unsigned int : 4; // 4-bit padding
unsigned int b : 4;
unsigned int : 4; // 4-bit padding
unsigned int c : 8;
};
void example5_padding(void) {
printf("\n=== EXAMPLE 5: Unnamed Bit Fields (Padding) ===\n\n");
printf("Layout with padding:\n");
printf(" Bits 0-3: field 'a'\n");
printf(" Bits 4-7: padding (unnamed)\n");
printf(" Bits 8-11: field 'b'\n");
printf(" Bits 12-15: padding (unnamed)\n");
printf(" Bits 16-23: field 'c'\n\n");
struct WithPadding p = {0};
p.a = 0xF;
p.b = 0xA;
p.c = 0x55;
printf("Values: a=0x%X, b=0x%X, c=0x%02X\n", p.a, p.b, p.c);
printf("Structure size: %zu bytes\n", sizeof(p));
}
/* ============================================================
* EXAMPLE 6: Zero-Width Bit Field (Force Alignment)
* ============================================================ */
struct ZeroWidth {
unsigned int a : 10;
unsigned int : 0; // Force next field to new storage unit
unsigned int b : 10;
};
struct NoZeroWidth {
unsigned int a : 10;
unsigned int b : 10; // Continues in same storage unit
};
void example6_zero_width(void) {
printf("\n=== EXAMPLE 6: Zero-Width Bit Field ===\n\n");
printf("Without zero-width:\n");
printf(" a and b packed together\n");
printf(" Size: %zu bytes\n\n", sizeof(struct NoZeroWidth));
printf("With zero-width (:0):\n");
printf(" b starts in new storage unit\n");
printf(" Size: %zu bytes\n", sizeof(struct ZeroWidth));
}
/* ============================================================
* EXAMPLE 7: Hardware Status Register Simulation
* ============================================================ */
struct StatusRegister {
unsigned int ready : 1;
unsigned int busy : 1;
unsigned int error : 1;
unsigned int overflow : 1;
unsigned int interrupt : 1;
unsigned int : 3; // Reserved bits
unsigned int errorCode : 8;
};
void printStatus(struct StatusRegister *sr) {
printf("Status Register:\n");
printf(" Ready: %s\n", sr->ready ? "YES" : "NO");
printf(" Busy: %s\n", sr->busy ? "YES" : "NO");
printf(" Error: %s\n", sr->error ? "YES" : "NO");
printf(" Overflow: %s\n", sr->overflow ? "YES" : "NO");
printf(" Interrupt: %s\n", sr->interrupt ? "YES" : "NO");
if (sr->error) {
printf(" Error Code: %u\n", sr->errorCode);
}
}
void example7_hardware_register(void) {
printf("\n=== EXAMPLE 7: Hardware Status Register ===\n\n");
struct StatusRegister sr = {0};
// Simulate device becoming ready
sr.ready = 1;
printStatus(&sr);
printf("\nSimulating error condition...\n\n");
sr.error = 1;
sr.errorCode = 42;
printStatus(&sr);
}
/* ============================================================
* EXAMPLE 8: Bit Fields with Union
* ============================================================ */
union Register {
uint16_t value;
struct {
uint16_t enable : 1;
uint16_t mode : 2;
uint16_t channel : 4;
uint16_t : 1; // Reserved
uint16_t data : 8;
} bits;
};
void example8_union_bitfield(void) {
printf("\n=== EXAMPLE 8: Bit Fields with Union ===\n\n");
union Register reg;
// Set via bit fields
reg.bits.enable = 1;
reg.bits.mode = 2;
reg.bits.channel = 5;
reg.bits.data = 0xAB;
printf("Setting via bit fields:\n");
printf(" enable = %u\n", reg.bits.enable);
printf(" mode = %u\n", reg.bits.mode);
printf(" channel = %u\n", reg.bits.channel);
printf(" data = 0x%02X\n", reg.bits.data);
printf(" Raw value = 0x%04X\n\n", reg.value);
// Set via raw value
reg.value = 0x1234;
printf("After setting raw value to 0x1234:\n");
printf(" enable = %u\n", reg.bits.enable);
printf(" mode = %u\n", reg.bits.mode);
printf(" channel = %u\n", reg.bits.channel);
printf(" data = 0x%02X\n", reg.bits.data);
}
/* ============================================================
* EXAMPLE 9: File Permissions
* ============================================================ */
struct FilePermissions {
unsigned int ownerRead : 1;
unsigned int ownerWrite : 1;
unsigned int ownerExecute : 1;
unsigned int groupRead : 1;
unsigned int groupWrite : 1;
unsigned int groupExecute : 1;
unsigned int otherRead : 1;
unsigned int otherWrite : 1;
unsigned int otherExecute : 1;
};
void printPermissions(struct FilePermissions p) {
printf("%c%c%c%c%c%c%c%c%c",
p.ownerRead ? 'r' : '-',
p.ownerWrite ? 'w' : '-',
p.ownerExecute ? 'x' : '-',
p.groupRead ? 'r' : '-',
p.groupWrite ? 'w' : '-',
p.groupExecute ? 'x' : '-',
p.otherRead ? 'r' : '-',
p.otherWrite ? 'w' : '-',
p.otherExecute ? 'x' : '-');
}
void example9_permissions(void) {
printf("\n=== EXAMPLE 9: File Permissions ===\n\n");
struct FilePermissions perm = {0};
// chmod 755
perm.ownerRead = perm.ownerWrite = perm.ownerExecute = 1;
perm.groupRead = perm.groupExecute = 1;
perm.otherRead = perm.otherExecute = 1;
printf("chmod 755: ");
printPermissions(perm);
printf("\n");
// chmod 644
perm = (struct FilePermissions){0};
perm.ownerRead = perm.ownerWrite = 1;
perm.groupRead = perm.otherRead = 1;
printf("chmod 644: ");
printPermissions(perm);
printf("\n");
printf("\nStructure size: %zu bytes\n", sizeof(perm));
printf("(9 bits packed into 4 bytes)\n");
}
/* ============================================================
* EXAMPLE 10: Network Packet Header
* ============================================================ */
struct PacketHeader {
unsigned int version : 4;
unsigned int priority : 3;
unsigned int : 1; // Reserved
unsigned int type : 8;
unsigned int length : 16;
};
void printPacketHeader(struct PacketHeader *hdr) {
printf("Packet Header:\n");
printf(" Version: %u\n", hdr->version);
printf(" Priority: %u\n", hdr->priority);
printf(" Type: 0x%02X\n", hdr->type);
printf(" Length: %u bytes\n", hdr->length);
}
void example10_packet_header(void) {
printf("\n=== EXAMPLE 10: Network Packet Header ===\n\n");
struct PacketHeader pkt = {
.version = 4,
.priority = 7,
.type = 0x11,
.length = 1500
};
printPacketHeader(&pkt);
printf("\nHeader size: %zu bytes\n", sizeof(pkt));
}
/* ============================================================
* EXAMPLE 11: Signed vs Unsigned Bit Fields
* ============================================================ */
struct SignedFields {
int signedField : 4; // Signed: -8 to 7
unsigned int unsignedField : 4; // Unsigned: 0 to 15
};
void example11_signed_unsigned(void) {
printf("\n=== EXAMPLE 11: Signed vs Unsigned ===\n\n");
struct SignedFields sf;
printf("4-bit signed range: -8 to 7\n");
printf("4-bit unsigned range: 0 to 15\n\n");
// Set both to same bit pattern
sf.signedField = 8; // Overflows to -8
sf.unsignedField = 8; // Stays as 8
printf("Setting both to 8:\n");
printf(" signedField = %d (overflowed!)\n", sf.signedField);
printf(" unsignedField = %u\n", sf.unsignedField);
sf.signedField = -1;
sf.unsignedField = 15; // Same bit pattern as -1 in 4 bits
printf("\nSigned = -1, Unsigned = 15:\n");
printf(" signedField = %d\n", sf.signedField);
printf(" unsignedField = %u\n", sf.unsignedField);
printf(" (Same bit pattern: 1111)\n");
}
/* ============================================================
* EXAMPLE 12: RGB Color with Alpha
* ============================================================ */
struct RGBAColor {
unsigned int red : 8;
unsigned int green : 8;
unsigned int blue : 8;
unsigned int alpha : 8;
};
void printColor(struct RGBAColor c) {
printf("RGBA(%3u, %3u, %3u, %3u)\n", c.red, c.green, c.blue, c.alpha);
}
void example12_rgba_color(void) {
printf("\n=== EXAMPLE 12: RGBA Color ===\n\n");
struct RGBAColor colors[] = {
{255, 0, 0, 255}, // Red
{0, 255, 0, 255}, // Green
{0, 0, 255, 255}, // Blue
{255, 255, 0, 128}, // Yellow, 50% transparent
{128, 128, 128, 255} // Gray
};
const char *names[] = {"Red", "Green", "Blue", "Yellow (50%)", "Gray"};
printf("Colors (packed in %zu bytes each):\n\n", sizeof(struct RGBAColor));
for (int i = 0; i < 5; i++) {
printf("%-15s: ", names[i]);
printColor(colors[i]);
}
}
/* ============================================================
* MAIN FUNCTION
* ============================================================ */
int main() {
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
printf("ā BIT FIELDS IN C - EXAMPLES ā\n");
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n");
example1_basic_bitfield();
example2_memory_savings();
example3_packed_data();
example4_range_limits();
example5_padding();
example6_zero_width();
example7_hardware_register();
example8_union_bitfield();
example9_permissions();
example10_packet_header();
example11_signed_unsigned();
example12_rgba_color();
printf("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
printf("All examples completed successfully!\n");
return 0;
}