跳转至

嵌入式C++教程——std::array vs C 数组,你们知道嘛?

写嵌入式代码时,你大概率会在两种写法间犹豫:int buf[16];std::array<int, 16> buf;。如果你像我(或者像你之前的文章风格那样)既爱性能又爱优雅,你会想知道:哪种更"嵌入式友好"?


为什么 std::array 看上去像"C 数组穿了件外套"——但其实更聪明

从表面看,std::array<T, N> 底层就是包含一个 T elems[N] 的聚合类型:内存上元素是连续的,元素布局没有神秘的开销。所以在很多场景下,std::array 与裸数组的性能、内存占用是等价的。换句话说,你不会因为换成 std::array 而在运行时付出额外费用。

std::array 把数组包进了一个类型:它有值语义(可以拷贝、赋值)、有 .size()、有 .data()、有 begin()/end()、能和 STL 算法无缝对接、支持 constexpr(在现代编译器下),还能作为模板参数被更好地推断。最关键的是,它把"长度是类型的一部分"这一信息显式化,调用接口时更不容易丢失长度信息。

换句话说:std::array 是"更安全、更现代"的数组。


裸 C 数组的老实巴交与致命天真

裸数组的优点是"零抽象",也就是你对内存完全可控:这在启动代码、驱动层、位于特定地址空间的缓冲区(比如映射到某个外设寄存器地址)非常重要。裸数组在 ABI、链接器、对齐方面不给你出难题——只要你知道自己在做什么,它非常可靠。

但裸数组也带来一堆常见的踩坑:它会在函数参数中退化为指针(因此 sizeof 在函数里会给出指针大小),不能直接拷贝赋值(b = a; 会编译不过),也没有任何边界或尺寸信息保护。嵌入式代码里,这些"方便的缺失"会让你经常写 memcpy、频繁查 N 是否写对、在审查时犯"忘记传长度"的低级错误。

一个真实场景:你把裸数组传给 C API 做 DMA,忘了告诉调用方长度,结果 DMA 越界写到你最珍贵的变量上。裸数组没有提醒你这类低概率高代价错误。


std::array 的优点:更安全、更可读、和现代 C++ 更友好

std::array 的日常优势可以总结为:语义清晰、接口友好、可与算法直接配合。例如,std::sort(a.begin(), a.end())std::span(a) 都是顺手可得的好处。std::array 可以 =, 复制,甚至作为函数返回值安全返回(不会退化),这在很多中层逻辑里能让代码更简洁、更少内存操作 bug。

在嵌入式上下文,这意味着测试代码、单元测试桩、缓冲区封装这些地方会更干净:你可以写成返回 std::array 的函数而不是整堆 memcpy。而且当编译器支持 constexpr 时,std::array 能在编译期构造常量表,代码既高效又安全。


那么什么时候应该继续用裸 C 数组?

std::array 很好,但并不是无敌。在下面几类场景,裸数组仍然是更合适的选择:

  1. 初始化阶段或早期引导代码(startup / crt0):在 main() 之前,C++ 的全局构造规则和运行时支持可能会麻烦。裸数组在这类代码里更直白、更可靠,尤其是当你需要绝对确保没有任何构造器或运行时代码介入时。
  2. 放在特定链接段 / 放到固定地址:像中断向量表、设备映射缓冲区、bootloader 的表格等,往往需要在链接脚本里精确声明对象位置和字节序。裸数组更直接映射到期望的内存布局,减少不必要的抽象。
  3. 严格的 ABI 或与外部 C API 的互操作,且你需要写裸指针:虽然 std::array.data(),但在一些非常讲究二进制兼容性的场景中,审计时用裸数组更直观(尤其是老代码基)。
  4. 极端资源受限且要避免编译器生成任何额外元信息:这类情况稀有,但存在于某些超嵌入式或者内核最底层代码中。

所以怎么说?

裸数组是简洁、可靠的工具,适合最接近硬件的那一层;std::array 是更现代、更安全、更贴合 C++ 思想的容器,适合业务逻辑、算法层以及绝大多数嵌入式应用代码。把二者当作工具箱里的两把刀:修理芯片引脚用军刀(裸数组),写协议解析和缓冲逻辑用精密小刀(std::array)。

最后一句鸡汤式建议:当你能把数组尺寸写成 std::array<T, N> 的模板参数时,就写成 std::array;当你必须在链接脚本或最早期的引导代码里精确控制每个字节时,回到裸数组,别害羞。嵌入式开发不是为了"保持纯粹",而是为了按实际需要用对工具——std::array 很多时候会让你代码更少、错误更少,偶尔你还是得把手伸进裸内存去修一修底层。


代码示例

查看完整可编译示例
#include <iostream>
#include <array>
#include <algorithm>
#include <cstring>
#include <iterator>

// std::array vs C数组的比较

void c_array_demo() {
    std::cout << "=== C Array Demo ===\n\n";

    // 声明和初始化
    int arr1[5] = {1, 2, 3, 4, 5};
    int arr2[] = {10, 20, 30};  // 自动推断大小
    int arr3[10] = {0};         // 零初始化

    std::cout << "arr1: ";
    for (int i = 0; i < 5; ++i) {
        std::cout << arr1[i] << " ";
    }
    std::cout << "\n";

    // 数组大小
    std::cout << "sizeof(arr1) = " << sizeof(arr1) << "\n";
    std::cout << "Element count = " << sizeof(arr1) / sizeof(arr1[0]) << "\n";

    // 数组退化(危险!)
    int* ptr = arr1;  // 退化为指针
    std::cout << "ptr points to: " << ptr << "\n";
    std::cout << "sizeof(ptr) = " << sizeof(ptr) << " (lost size info!)\n";

    // 边界检查:无!
    // arr1[10] = 99;  // 未定义行为,越界访问

    // 不能直接复制
    int arr4[5];
    // arr4 = arr1;     // 编译错误!
    std::memcpy(arr4, arr1, sizeof(arr1));  // 需要memcpy

    // 不能直接比较
    // if (arr4 == arr1) { }  // 比较的是地址,不是内容
}

void std_array_demo() {
    std::cout << "\n=== std::array Demo ===\n\n";

    // 声明和初始化
    std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
    std::array<int, 3> arr2 = {10, 20, 30};
    std::array<int, 10> arr3{};  // 零初始化

    std::cout << "arr1: ";
    for (size_t i = 0; i < arr1.size(); ++i) {
        std::cout << arr1[i] << " ";
    }
    std::cout << "\n";

    // 数组大小
    std::cout << "arr1.size() = " << arr1.size() << "\n";
    std::cout << "arr1.max_size() = " << arr1.max_size() << "\n";
    std::cout << "sizeof(arr1) = " << sizeof(arr1) << "\n";
    std::cout << "empty? " << (arr1.empty() ? "yes" : "no") << "\n";

    // 不退化,保持类型信息
    auto& ref = arr1;
    std::cout << "sizeof(ref) = " << sizeof(ref) << " (preserved!)\n";

    // 边界检查(at方法)
    try {
        std::cout << "arr1.at(2) = " << arr1.at(2) << "\n";
        std::cout << "arr1.at(10) = ";  // 越界
        std::cout << arr1.at(10) << "\n";
    } catch (const std::out_of_range& e) {
        std::cout << "caught exception: " << e.what() << "\n";
    }

    // 可以直接复制
    std::array<int, 5> arr4 = arr1;
    std::cout << "\narr4 (copy of arr1): ";
    for (int v : arr4) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    // 可以直接比较
    std::array<int, 5> arr5 = {1, 2, 3, 4, 5};
    std::cout << "arr4 == arr5? " << (arr4 == arr5 ? "yes" : "no") << "\n";

    // 可以赋值
    arr4 = {10, 20, 30, 40, 50};
    std::cout << "After assignment, arr4: ";
    for (int v : arr4) {
        std::cout << v << " ";
    }
    std::cout << "\n";
}

void iteration_demo() {
    std::cout << "\n=== Iteration Comparison ===\n\n";

    // C数组
    int c_arr[] = {1, 2, 3, 4, 5};

    std::cout << "C array:\n";
    std::cout << "  Index loop: ";
    for (size_t i = 0; i < sizeof(c_arr) / sizeof(c_arr[0]); ++i) {
        std::cout << c_arr[i] << " ";
    }
    std::cout << "\n";

    std::cout << "  Range-based for (C++11): ";
    for (int v : c_arr) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    // std::array
    std::array<int, 5> std_arr = {1, 2, 3, 4, 5};

    std::cout << "\nstd::array:\n";
    std::cout << "  Index loop: ";
    for (size_t i = 0; i < std_arr.size(); ++i) {
        std::cout << std_arr[i] << " ";
    }
    std::cout << "\n";

    std::cout << "  Range-based for: ";
    for (int v : std_arr) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    std::cout << "  Iterator: ";
    for (auto it = std_arr.begin(); it != std_arr.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    std::cout << "  Reverse iterator: ";
    for (auto it = std_arr.rbegin(); it != std_arr.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    std::cout << "  std::for_each: ";
    std::for_each(std_arr.begin(), std_arr.end(), [](int v) {
        std::cout << v << " ";
    });
    std::cout << "\n";
}

void stl_integration_demo() {
    std::cout << "\n=== STL Integration ===\n\n";

    std::array<int, 10> arr = {5, 2, 8, 1, 9, 3, 7, 4, 6, 0};

    std::cout << "Original: ";
    for (int v : arr) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    // 排序
    std::sort(arr.begin(), arr.end());
    std::cout << "Sorted:   ";
    for (int v : arr) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    // 查找
    auto it = std::find(arr.begin(), arr.end(), 7);
    if (it != arr.end()) {
        std::cout << "Found 7 at index " << (it - arr.begin()) << "\n";
    }

    // 二分查找
    bool found = std::binary_search(arr.begin(), arr.end(), 5);
    std::cout << "Binary search for 5: " << (found ? "found" : "not found") << "\n";

    // 计数
    std::array<int, 10> arr2 = {1, 2, 2, 3, 2, 4, 2, 5, 2, 6};
    size_t count = std::count(arr2.begin(), arr2.end(), 2);
    std::cout << "Count of 2 in arr2: " << count << "\n";

    // 填充
    std::array<int, 5> fill_arr;
    fill_arr.fill(42);
    std::cout << "Filled array: ";
    for (int v : fill_arr) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    // 交换
    std::array<int, 5> a = {1, 2, 3, 4, 5};
    std::array<int, 5> b = {10, 20, 30, 40, 50};
    std::cout << "\nBefore swap:\n";
    std::cout << "  a: ";
    for (int v : a) std::cout << v << " ";
    std::cout << "\n  b: ";
    for (int v : b) std::cout << v << " ";
    std::cout << "\n";

    a.swap(b);
    std::cout << "After swap:\n";
    std::cout << "  a: ";
    for (int v : a) std::cout << v << " ";
    std::cout << "\n  b: ";
    for (int v : b) std::cout << v << " ";
    std::cout << "\n";
}

void data_access_demo() {
    std::cout << "\n=== Data Access ===\n\n";

    std::array<int, 5> arr = {10, 20, 30, 40, 50};

    // data() 返回原始指针
    int* ptr = arr.data();
    std::cout << "Via data(): ";
    for (size_t i = 0; i < arr.size(); ++i) {
        std::cout << ptr[i] << " ";
    }
    std::cout << "\n";

    // front() 和 back()
    std::cout << "front() = " << arr.front() << "\n";
    std::cout << "back() = " << arr.back() << "\n";

    // 与C API互操作
    std::array<char, 64> buf;
    std::strcpy(buf.data(), "Hello, std::array!");
    std::cout << "String: " << buf.data() << "\n";

    // 使用memcpy
    std::array<int, 5> src = {1, 2, 3, 4, 5};
    std::array<int, 5> dst;
    std::memcpy(dst.data(), src.data(), sizeof(src));
    std::cout << "Copied: ";
    for (int v : dst) {
        std::cout << v << " ";
    }
    std::cout << "\n";
}

void constexpr_demo() {
    std::cout << "\n=== Compile-Time Features ===\n\n";

    // 编译期构造
    constexpr std::array<int, 5> fib = [] {
        std::array<int, 5> arr{};
        arr[0] = 0;
        arr[1] = 1;
        for (size_t i = 2; i < arr.size(); ++i) {
            arr[i] = arr[i-1] + arr[i-2];
        }
        return arr;
    }();

    std::cout << "Compile-time Fibonacci: ";
    for (int v : fib) {
        std::cout << v << " ";
    }
    std::cout << "\n";

    // 编译期大小检查
    static_assert(fib.size() == 5, "Size must be 5");

    // 作为模板参数
    template<size_t N>
    void print_array_size(const std::array<int, N>&) {
        std::cout << "Array size (template param): " << N << "\n";
    }

    std::array<int, 10> arr;
    print_array_size(arr);
}

int main() {
    c_array_demo();
    std_array_demo();
    iteration_demo();
    stl_integration_demo();
    data_access_demo();
    constexpr_demo();

    std::cout << "\n=== Key Takeaways ===\n";
    std::cout << "1. std::array provides size info, doesn't decay to pointer\n";
    std::cout << "2. Boundary checking with at() method\n";
    std::cout << "3. Copyable, comparable, assignable\n";
    std::cout << "4. Full STL algorithm support\n";
    std::cout << "5. Zero overhead compared to C arrays\n";
    std::cout << "6. Prefer std::array except in low-level startup code\n";

    return 0;
}
#include <iostream>
#include <array>
#include <algorithm>
#include <cstring>
#include <cstdint>

// std::array 在实际嵌入式场景中的应用

// 示例1:状态机状态表
enum class State {
    Idle,
    Running,
    Paused,
    Error
};

enum class Event {
    Start,
    Stop,
    Pause,
    Resume,
    Error
};

struct StateTransition {
    State current;
    Event event;
    State next;
};

constexpr std::array<StateTransition, 8> state_table = {{
    {State::Idle, Event::Start, State::Running},
    {State::Running, Event::Stop, State::Idle},
    {State::Running, Event::Pause, State::Paused},
    {State::Paused, Event::Resume, State::Running},
    {State::Paused, Event::Stop, State::Idle},
    {State::Error, Event::Stop, State::Idle},
    // 可以添加更多转换...
}};

State get_next_state(State current, Event event) {
    auto it = std::find_if(state_table.begin(), state_table.end(),
        [current, event](const StateTransition& t) {
            return t.current == current && t.event == event;
        });
    return (it != state_table.end()) ? it->next : State::Error;
}

void state_machine_demo() {
    std::cout << "=== State Machine with std::array ===\n\n";

    State state = State::Idle;

    auto print_state = [](State s) {
        switch (s) {
            case State::Idle:    std::cout << "Idle"; break;
            case State::Running: std::cout << "Running"; break;
            case State::Paused:  std::cout << "Paused"; break;
            case State::Error:   std::cout << "Error"; break;
        }
    };

    std::array<Event, 6> events = {
        Event::Start, Event::Pause, Event::Resume,
        Event::Stop, Event::Start, Event::Error
    };

    for (Event e : events) {
        print_state(state);
        std::cout << " + ";
        switch (e) {
            case Event::Start:  std::cout << "Start"; break;
            case Event::Stop:   std::cout << "Stop"; break;
            case Event::Pause:  std::cout << "Pause"; break;
            case Event::Resume: std::cout << "Resume"; break;
            case Event::Error:  std::cout << "Error"; break;
        }
        std::cout << " -> ";
        state = get_next_state(state, e);
        print_state(state);
        std::cout << "\n";
    }
}

// 示例2:环形缓冲区
template<typename T, size_t N>
class RingBuffer {
    std::array<T, N> buffer_;
    size_t head_ = 0;
    size_t tail_ = 0;

    // 要求N是2的幂
    static_assert((N & (N - 1)) == 0, "Size must be power of 2");
    static constexpr size_t mask_ = N - 1;

public:
    bool push(const T& value) {
        size_t next = (head_ + 1) & mask_;
        if (next == tail_) {
            return false;  // Full
        }
        buffer_[head_] = value;
        head_ = next;
        return true;
    }

    bool pop(T& out) {
        if (head_ == tail_) {
            return false;  // Empty
        }
        out = buffer_[tail_];
        tail_ = (tail_ + 1) & mask_;
        return true;
    }

    bool empty() const { return head_ == tail_; }
    bool full() const { return ((head_ + 1) & mask_) == tail_; }
    size_t size() const { return (head_ - tail_) & mask_; }

    const std::array<T, N>& data() const { return buffer_; }
};

void ring_buffer_demo() {
    std::cout << "\n=== Ring Buffer with std::array ===\n\n";

    RingBuffer<int, 8> rb;

    // Push values
    for (int i = 0; i < 7; ++i) {
        bool ok = rb.push(i);
        std::cout << "Push " << i << ": " << (ok ? "success" : "failed") << "\n";
    }

    std::cout << "Buffer size: " << rb.size() << "\n";
    std::cout << "Buffer full: " << (rb.full() ? "yes" : "no") << "\n";

    // Pop values
    std::cout << "\nPopping values:\n";
    int val;
    while (rb.pop(val)) {
        std::cout << "  " << val << "\n";
    }

    std::cout << "Buffer empty: " << (rb.empty() ? "yes" : "no") << "\n";
}

// 示例3:硬件寄存器映射(演示用)
class RegisterMap {
    std::array<uint32_t, 16> registers_;

public:
    RegisterMap() { registers_.fill(0); }

    // 读写寄存器
    uint32_t read(size_t index) const {
        if (index < registers_.size()) {
            return registers_[index];
        }
        return 0;
    }

    void write(size_t index, uint32_t value) {
        if (index < registers_.size()) {
            registers_[index] = value;
        }
    }

    // 位操作
    void set_bit(size_t index, size_t bit) {
        if (index < registers_.size() && bit < 32) {
            registers_[index] |= (1U << bit);
        }
    }

    void clear_bit(size_t index, size_t bit) {
        if (index < registers_.size() && bit < 32) {
            registers_[index] &= ~(1U << bit);
        }
    }

    // 导出原始数据(用于DMA等)
    uint32_t* data() { return registers_.data(); }
    const uint32_t* data() const { return registers_.data(); }
};

void register_map_demo() {
    std::cout << "\n=== Register Map with std::array ===\n\n";

    RegisterMap regs;

    // 写入一些寄存器
    regs.write(0, 0x12345678);
    regs.write(1, 0xABCDEF00);
    regs.set_bit(2, 5);
    regs.set_bit(2, 10);

    // 读取并显示
    for (size_t i = 0; i < 4; ++i) {
        std::cout << "Reg[" << i << "] = 0x" << std::hex << regs.read(i) << std::dec << "\n";
    }

    // 与C API互操作
    std::array<uint32_t, 16> copy;
    std::memcpy(copy.data(), regs.data(), sizeof(uint32_t) * 16);

    std::cout << "\nCopied via memcpy, first value: 0x" << std::hex << copy[0] << std::dec << "\n";
}

// 示例4:查表
template<typename T, size_t TABLE_SIZE>
class LookupTable {
    std::array<T, TABLE_SIZE> table_;

public:
    explicit LookupTable(const std::array<T, TABLE_SIZE>& table) : table_(table) {}

    // 线性插值查表
    T lookup(float index) const {
        if (index <= 0) return table_[0];
        if (index >= TABLE_SIZE - 1) return table_[TABLE_SIZE - 1];

        size_t i = static_cast<size_t>(index);
        float frac = index - i;

        return table_[i] + frac * (table_[i + 1] - table_[i]);
    }

    // 直接查表
    const T& operator[](size_t index) const {
        return table_[index];
    }

    size_t size() const { return TABLE_SIZE; }
};

void lookup_table_demo() {
    std::cout << "\n=== Lookup Table with std::array ===\n\n";

    // 正弦表(简化版)
    constexpr std::array<float, 16> sin_table = [] {
        std::array<float, 16> table{};
        for (size_t i = 0; i < 16; ++i) {
            float angle = i * 3.14159f / 8.0f;  // 0 to 2pi
            table[i] = std::sin(angle);
        }
        return table;
    }();

    LookupTable<float, 16> sin_lut(sin_table);

    std::cout << "Sine lookup:\n";
    for (float f = 0.0f; f < 3.2f; f += 0.5f) {
        float sin_val = sin_lut.lookup(f * 5.0f);  // Scale to table index
        std::cout << "  sin(" << f << ") ≈ " << sin_val << "\n";
    }
}

// 示例5:固定大小字符串缓冲区
template<size_t N>
class StaticString {
    std::array<char, N> buffer_;

public:
    StaticString() {
        buffer_[0] = '\0';
    }

    StaticString(const char* str) {
        set(str);
    }

    void set(const char* str) {
        if (str) {
            std::strncpy(buffer_.data(), str, N - 1);
            buffer_[N - 1] = '\0';
        } else {
            buffer_[0] = '\0';
        }
    }

    const char* c_str() const {
        return buffer_.data();
    }

    size_t length() const {
        return std::strlen(buffer_.data());
    }

    bool empty() const {
        return buffer_[0] == '\0';
    }

    // 格式化(简化版)
    int printf(const char* format, ...) {
        va_list args;
        va_start(args, format);
        int result = std::vsnprintf(buffer_.data(), N, format, args);
        va_end(args);
        return result;
    }
};

void static_string_demo() {
    std::cout << "\n=== Static String with std::array ===\n\n";

    StaticString<32> str1("Hello");
    StaticString<64> str2;

    std::cout << "str1: \"" << str1.c_str() << "\" (len=" << str1.length() << ")\n";

    str2.set("World");
    std::cout << "str2: \"" << str2.c_str() << "\"\n";

    str2.printf("Value: %d, Hex: 0x%X", 42, 0xABCD);
    std::cout << "Formatted: \"" << str2.c_str() << "\"\n";
}

// 示例6:传感器数据缓冲
struct SensorData {
    uint32_t timestamp;
    float value;
    uint8_t status;
};

class SensorBuffer {
    std::array<SensorData, 100> buffer_;
    size_t count_ = 0;

public:
    bool add(const SensorData& data) {
        if (count_ >= buffer_.size()) {
            return false;
        }
        buffer_[count_++] = data;
        return true;
    }

    const SensorData* get_latest() const {
        if (count_ == 0) return nullptr;
        return &buffer_[count_ - 1];
    }

    const SensorData* get(size_t index) const {
        if (index >= count_) return nullptr;
        return &buffer_[index];
    }

    size_t count() const { return count_; }

    void clear() { count_ = 0; }

    // 统计
    float average() const {
        if (count_ == 0) return 0.0f;
        float sum = 0.0f;
        for (size_t i = 0; i < count_; ++i) {
            sum += buffer_[i].value;
        }
        return sum / count_;
    }

    float min() const {
        if (count_ == 0) return 0.0f;
        float m = buffer_[0].value;
        for (size_t i = 1; i < count_; ++i) {
            if (buffer_[i].value < m) m = buffer_[i].value;
        }
        return m;
    }

    float max() const {
        if (count_ == 0) return 0.0f;
        float m = buffer_[0].value;
        for (size_t i = 1; i < count_; ++i) {
            if (buffer_[i].value > m) m = buffer_[i].value;
        }
        return m;
    }
};

void sensor_buffer_demo() {
    std::cout << "\n=== Sensor Buffer with std::array ===\n\n";

    SensorBuffer buffer;

    // 添加一些传感器数据
    for (int i = 0; i < 10; ++i) {
        SensorData data;
        data.timestamp = i * 100;
        data.value = 20.0f + i * 0.5f;
        data.status = 0;
        buffer.add(data);
    }

    std::cout << "Collected " << buffer.count() << " samples\n";
    std::cout << "Average: " << buffer.average() << "\n";
    std::cout << "Min: " << buffer.min() << "\n";
    std::cout << "Max: " << buffer.max() << "\n";

    const SensorData* latest = buffer.get_latest();
    if (latest) {
        std::cout << "Latest: " << latest->value << " at t=" << latest->timestamp << "\n";
    }
}

int main() {
    state_machine_demo();
    ring_buffer_demo();
    register_map_demo();
    lookup_table_demo();
    static_string_demo();
    sensor_buffer_demo();

    std::cout << "\n=== Key Takeaways ===\n";
    std::cout << "1. std::array perfect for fixed-size collections\n";
    std::cout << "2. State tables, ring buffers, lookup tables all benefit\n";
    std::cout << "3. Zero overhead, full type safety\n";
    std::cout << "4. Easy integration with C APIs via .data()\n";
    std::cout << "5. Compile-time size enables template optimizations\n";

    return 0;
}