====== Lab 06 - Structs and enums ====== ===== Structs ===== * A struct groups variables under one name. * Members can be of different types. * Access with the dot operator (''.'') or arrow (''->'') if you have a pointer. * Structs can be copied by value (unlike arrays!). * ''sizeof(struct)'' may include padding bytes - compiler aligns fields for efficiency. struct Point { int x; int y; }; struct Point p = {10, 20}; printf("%d %d", p.x, p.y); * Use ''typedef'' for convenience: typedef struct { char name[20]; int age; } Person; ===== Unions ===== * All members share the same memory. * Size = size of the largest member. * Only one field is valid at a time. * Writing to one member overwrites all others. * Common in embedded systems or binary data parsing. union Number { int i; float f; char c; }; union Number n; n.f = 3.14; printf("%f", n.f); ===== Enums ===== * Named integer constants for clarity. * Default values start at 0, unless specified. * Enum identifiers are just integers. * You can assign any int, even if not in the enum (C does not check validity). enum Color { RED, GREEN = 5, BLUE }; enum Color c = BLUE; printf("%d\n", c); // prints 6 ===== Bit Fields ===== * Compact representation of flags or small numbers inside structs. * Specify number of bits per field. * Bit-field ordering (left/right) is implementation-defined. * Be careful mixing signed/unsigned types. * Cannot take the address of a bit-field. struct Status { unsigned int power : 1; unsigned int error : 1; unsigned int mode : 2; // 0–3 }; ===== Preprocessor ===== * Runs before compilation - simple text substitution. * Compilers can set macros directly from the command line * Use ''-E'' to see the preprocessor phase output or ''-S'' for assembly * Common uses: * ''#define'' macros * ''#ifdef'', ''#ifndef'', ''#endif'' for conditional compilation * ''#include'' for file inclusion * Always parenthesize macro arguments: #define SQUARE(x) ((x)*(x)) // OK #define SQUARE(x) (x*x) // WRONG #define PI 3.14159 #define SQUARE(x) ((x)*(x)) #define DEBUG #ifdef DEBUG printf("Debug mode on\n"); #endif ---- ==== Task 1: Struct + Enum ==== Create a program that defines: enum Department { IT, HR, SALES }; struct Employee { char name[30]; int age; enum Department dept; }; * Read info for 3 employees from the user. * Print them in a formatted table. * Use a helper function ''const char* dept_to_str(enum Department d)'' to return department names. ==== Task 2: Union + Bit Fields ==== Define a union for storing a 32-bit register as either: * an ''unsigned int raw;'' value, or * a struct of bit fields showing: struct { unsigned int enable : 1; unsigned int mode : 2; unsigned int error : 1; unsigned int reserved : 28; }; Your program will: * Allow user to enter a register value in hex (''0x...'') * Print individual bit field values. ==== Task 3: Preprocessor + Conditional Compilation ==== Use a macro for debug control: #define DEBUG 1 * Wrap debug `printf()` statements in ''#ifdef DEBUG'' * Print a message like: #ifdef DEBUG printf("[DEBUG] Value = %d\n", x); #endif * Try compiling after commenting out `#define DEBUG` or modifying the code to print debug messages only when the compiler defines the macro.