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.
courses/be5b99cpl/labs/lab06.txt · Last modified: 2025/10/29 10:37 by ulricji1