112. UART Frame Builder

Create a class named Frame that represents a UART transmit frame with a maximum capacity of 16 bytes.

The class must internally store bytes using a fixed-size array and must not use dynamic memory allocation.

You are required to overload operators to make frame construction intuitive and safe for firmware-style usage.

Requirements

You must implement the following in the Frame class:

  • A fixed internal buffer of 16 bytes
  • A variable to track the current frame size
  • operator+= to append a single byte to the frame
  • operator[] to access a byte by index for read-only purposes
  • A method to retrieve the current frame size

The frame must never exceed 16 bytes. The input provided will always respect this limit.

Program Behavior

Your program must:

  1. Read an integer n — the number of bytes to append
  2. Read n integers, each representing a byte value in the range 0–255
  3. Append each byte to the frame using the overloaded operator+=
  4. Print the final frame contents in order, separated by single spaces

 

Input Format

n
b1 b2 b3 ... bn
  • n is an integer where 1 ≤ n ≤ 16
  • Each b is an integer where 0 ≤ b ≤ 255

Output Format

b1 b2 b3 ... bn

Each value must be printed as a decimal integer, separated by a single space.

 

Example 1

Input:

4
10 20 30 40

Output:

10 20 30 40

 

Example 2

Input:

3
255 0 128

Output:

255 0 128

 

Constraints

  • Internal storage type must be uint8_t
  • Maximum frame size is 16 bytes
  • No dynamic memory allocation (new, malloc, STL containers, etc.)
  • Only operator+= and operator[] may be used for frame access
  • Output formatting must match exactly

 

 

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.