106. Register Bitwise Operations

In embedded and firmware systems, hardware registers are often manipulated using bitwise operations such as OR and AND to set, clear, or mask specific bits.

Your task is to implement a C++ class named Reg32 that represents a 32-bit hardware register and supports controlled bitwise operations using operator overloading.

The register must store an unsigned 32-bit value and allow modification using bitwise OR and AND assignments, similar to how registers are manipulated in low-level firmware code.

Task Requirements

Implement a class Reg32 that:

  1. Stores a uint32_t value internally.
  2. Supports the following operations with a 32-bit unsigned integer:
    • reg |= x; → Performs a bitwise OR between the register value and x
    • reg &= x; → Performs a bitwise AND between the register value and x
  3. Overloads:
    • operator uint32_t() const;
      so the object can be printed or used as a normal unsigned integer.

Program Flow

  1. Read three unsigned 32-bit integers:
    1. initial_value  or_value  and_value
      
  2. Create a Reg32 object initialized with initial_value.
  3. Apply the following operations in order:
    1. reg |= or_value;
      reg &= and_value;
      
  4. Print the final value stored in the register.

Input Format

Three space-separated unsigned integers:

initial_value or_value and_value

Output Format

A single unsigned integer representing the final register value after both operations.

 

Example

Input:

8 5 14

Binary Steps:

8   = 1000₂
5   = 0101₂  → OR  → 1101₂ (13)
14  = 1110₂  → AND → 1100₂ (12)

Output:

12

 

Constraints

  • Use operator overloading for |= and &=
  • operator uint32_t() must be implemented
  • Use uint32_t for all register-related values
  • Output must match exactly
  • No additional output or formatting is allowed

 

 

 

 

Need Help? Refer to the Quick Guide below

In C, operators like +, -, ==, or [] only work on built-in types (int, float). If you have a custom struct (e.g., Complex), you have to write clumsy functions like add_complex(a, b).

In C++, Operator Overloading allows you to define how standard operators behave for your custom classes. This lets you treat hardware objects or math structures just like native types.

Syntax & Usage

1. Basic Arithmetic (+, -)

Making complex data types (like Vectors or Fixed-Point numbers) intuitive to use.

class Vector {
public:
    int x, y;
    Vector(int x, int y) : x(x), y(y) {}

    // Overload '+' operator
    Vector operator+(const Vector& other) const {
        // Return a new object with the sum
        return Vector(this->x + other.x, this->y + other.y);
    }
};

// Usage
Vector v1(1, 2), v2(3, 4);
Vector v3 = v1 + v2; // v3 is (4, 6). Reads like math!

2. Array Subscript ([])

Allows a driver class to access internal memory or hardware buffers like a standard C array.

class EEPROM {
    uint32_t base_addr;
public:
    // Overload [] to read byte at offset
    uint8_t operator[](int offset) {
        return *(volatile uint8_t*)(base_addr + offset);
    }
};

EEPROM memory;
uint8_t val = memory[5]; // Reads hardware address (base + 5)

3. Comparison (==)

Simplify checking sensor states.

bool operator==(const SensorData& a, const SensorData& b) {
    return (a.id == b.id) && (a.val == b.val);
}

if (current_reading == last_reading) { /* ... */ }

How It Works (Syntactic Sugar)

ExpressionCompiler Translates To
a + ba.operator+(b)
a == ba.operator==(b)
obj[i]obj.operator[](i)
ptr->xptr.operator->() (Smart Pointers)

Relevance in Embedded/Firmware

1. Fixed-Point Math

On microcontrollers without an FPU (Floating Point Unit), we often use integers to represent decimals (e.g., 100 = 1.00).

By wrapping this in a class and overloading +, -, *, /, you can write math code that looks like standard float math but compiles to efficient integer instructions.

2. Hardware Buffers

Overloading [] allows you to create "Safe Arrays" that check bounds before accessing memory.

uint8_t& operator[](int i) {
    assert(i < SIZE); // Safety check in Debug mode
    return buffer[i];
}

3. Bit Manipulation

You can overload | and & for enum class types (which don't support them by default) to create type-safe flag systems.

Common Pitfalls (Practical Tips)

PitfallDetails
❌ Changing MeaningDon't overload + to do subtraction. Operators should follow "Principle of Least Astonishment." If a + b deletes a file, no one will understand your code.
❌ Logical OperatorsAvoid overloading && and `
❌ Unary vs Binaryoperator++() (Prefix) and operator++(int) (Postfix) have different signatures. Mixing them up causes infinite recursion or wrong behavior.
✅ Zero OverheadIf implemented correctly (often inline), operator overloading has zero CPU cost compared to a manual function call.