You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在现代C++中将多块不同地址的数组视为单一连续数组?

现代C++实现跨固定地址数组的连续访问封装

针对单片机开发中固定地址分散数组的问题,我们可以用C++2x特性封装一个类,将两块物理不连续的数组抽象为逻辑连续的容器,支持随机访问、迭代器和标准库算法,无需手动处理索引切换。

1. 静态分配固定地址数组

保留原有的section属性配置,根据编译期常量CONF_BUFF_SIZE和BUFF_MAX分配两块数组:

#include <cstddef>

// 编译期常量(根据项目实际配置)
constexpr std::size_t BUFF_MAX = 800;
constexpr std::size_t CONF_BUFF_SIZE = 1200;

// 第一块固定地址数组(0x1000,SRAM_BANK2)
alignas(unsigned char)
unsigned char buffer1[std::min(CONF_BUFF_SIZE, BUFF_MAX)] __attribute__((section("SRAM_BANK2")));

// 第二块固定地址数组(仅当容量超限时分配,0xF000,SRAM_BANK4)
#ifdef CONF_BUFF_SIZE > BUFF_MAX
alignas(unsigned char)
unsigned char buffer2[CONF_BUFF_SIZE - BUFF_MAX] __attribute__((section("SRAM_BANK4")));
#endif

2. 封装连续访问类

实现SplitBuffer类,封装两块数组的指针和大小,重载operator[]并实现随机访问迭代器,让外部使用时完全感知不到数组的物理分散:

#include <iterator>

class SplitBuffer {
public:
    using value_type = unsigned char;
    using pointer = value_type*;
    using reference = value_type&;
    using const_reference = const value_type&;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;

    // 随机访问迭代器
    class iterator {
    public:
        using iterator_category = std::random_access_iterator_tag;
        using value_type = SplitBuffer::value_type;
        using pointer = SplitBuffer::pointer;
        using reference = SplitBuffer::reference;
        using difference_type = SplitBuffer::difference_type;

        constexpr iterator(pointer first_buf, size_type first_size, pointer second_buf, size_type second_size, size_type pos)
            : first_buf_(first_buf), first_size_(first_size), second_buf_(second_buf), second_size_(second_size), pos_(pos) {}

        constexpr reference operator*() const {
            return pos_ < first_size_ ? first_buf_[pos_] : second_buf_[pos_ - first_size_];
        }

        constexpr pointer operator->() const {
            return pos_ < first_size_ ? &first_buf_[pos_] : &second_buf_[pos_ - first_size_];
        }

        constexpr iterator& operator++() { return ++pos_, *this; }
        constexpr iterator operator++(int) { auto tmp = *this; ++pos_; return tmp; }
        constexpr iterator& operator--() { return --pos_, *this; }
        constexpr iterator operator--(int) { auto tmp = *this; --pos_; return tmp; }

        constexpr iterator operator+(difference_type n) const {
            return iterator(first_buf_, first_size_, second_buf_, second_size_, pos_ + n);
        }

        constexpr iterator& operator+=(difference_type n) { return pos_ += n, *this; }
        constexpr iterator operator-(difference_type n) const {
            return iterator(first_buf_, first_size_, second_buf_, second_size_, pos_ - n);
        }

        constexpr iterator& operator-=(difference_type n) { return pos_ -= n, *this; }
        constexpr difference_type operator-(const iterator& other) const { return pos_ - other.pos_; }
        constexpr reference operator[](difference_type n) const { return *(*this + n); }

        constexpr bool operator==(const iterator& other) const = default;
        constexpr auto operator<=>(const iterator& other) const = default;

    private:
        pointer first_buf_;
        size_type first_size_;
        pointer second_buf_;
        size_type second_size_;
        size_type pos_;
    };

    // 常量随机访问迭代器
    class const_iterator {
    public:
        using iterator_category = std::random_access_iterator_tag;
        using value_type = SplitBuffer::value_type;
        using pointer = const value_type*;
        using reference = const value_type&;
        using difference_type = SplitBuffer::difference_type;

        constexpr const_iterator(pointer first_buf, size_type first_size, pointer second_buf, size_type second_size, size_type pos)
            : first_buf_(first_buf), first_size_(first_size), second_buf_(second_buf), second_size_(second_size), pos_(pos) {}

        constexpr reference operator*() const {
            return pos_ < first_size_ ? first_buf_[pos_] : second_buf_[pos_ - first_size_];
        }

        constexpr pointer operator->() const {
            return pos_ < first_size_ ? &first_buf_[pos_] : &second_buf_[pos_ - first_size_];
        }

        constexpr const_iterator& operator++() { return ++pos_, *this; }
        constexpr const_iterator operator++(int) { auto tmp = *this; ++pos_; return tmp; }
        constexpr const_iterator& operator--() { return --pos_, *this; }
        constexpr const_iterator operator--(int) { auto tmp = *this; --pos_; return tmp; }

        constexpr const_iterator operator+(difference_type n) const {
            return const_iterator(first_buf_, first_size_, second_buf_, second_size_, pos_ + n);
        }

        constexpr const_iterator& operator+=(difference_type n) { return pos_ += n, *this; }
        constexpr const_iterator operator-(difference_type n) const {
            return const_iterator(first_buf_, first_size_, second_buf_, second_size_, pos_ - n);
        }

        constexpr const_iterator& operator-=(difference_type n) { return pos_ -= n, *this; }
        constexpr difference_type operator-(const const_iterator& other) const { return pos_ - other.pos_; }
        constexpr reference operator[](difference_type n) const { return *(*this + n); }

        constexpr bool operator==(const const_iterator& other) const = default;
        constexpr auto operator<=>(const const_iterator& other) const = default;

    private:
        pointer first_buf_;
        size_type first_size_;
        pointer second_buf_;
        size_type second_size_;
        size_type pos_;
    };

    constexpr SplitBuffer(pointer first_buf, size_type first_size, pointer second_buf, size_type second_size)
        : first_buf_(first_buf), first_size_(first_size), second_buf_(second_buf), second_size_(second_size) {}

    // 获取总容量
    constexpr size_type size() const { return first_size_ + second_size_; }

    // 随机访问重载
    constexpr reference operator[](size_type idx) {
        return idx < first_size_ ? first_buf_[idx] : second_buf_[idx - first_size_];
    }

    constexpr const_reference operator[](size_type idx) const {
        return idx < first_size_ ? first_buf_[idx] : second_buf_[idx - first_size_];
    }

    // 迭代器接口
    constexpr iterator begin() { return iterator(first_buf_, first_size_, second_buf_, second_size_, 0); }
    constexpr iterator end() { return iterator(first_buf_, first_size_, second_buf_, second_size_, size()); }
    constexpr const_iterator begin() const { return const_iterator(first_buf_, first_size_, second_buf_, second_size_, 0); }
    constexpr const_iterator end() const { return const_iterator(first_buf_, first_size_, second_buf_, second_size_, size()); }
    constexpr const_iterator cbegin() const { return begin(); }
    constexpr const_iterator cend() const { return end(); }

private:
    pointer first_buf_;
    size_type first_size_;
    pointer second_buf_;
    size_type second_size_;
};

3. 全局实例化与使用

根据编译期条件初始化全局SplitBuffer实例,之后即可像操作普通连续数组一样使用:

// 全局缓冲实例
#ifdef CONF_BUFF_SIZE > BUFF_MAX
constexpr SplitBuffer global_buffer(buffer1, sizeof(buffer1)/sizeof(buffer1[0]), buffer2, sizeof(buffer2)/sizeof(buffer2[0]));
#else
constexpr SplitBuffer global_buffer(buffer1, sizeof(buffer1)/sizeof(buffer1[0]), nullptr, 0);
#endif

// 使用示例
int main() {
    // 修改第二块数组的元素(假设CONF_BUFF_SIZE=1200,BUFF_MAX=800)
    global_buffer[1000] = 0xFE;

    // 范围for遍历初始化
    for (auto& byte : global_buffer) {
        byte = 0x00;
    }

    // 使用标准库算法
    #include <algorithm>
    std::fill(global_buffer.begin(), global_buffer.end(), 0xFF);

    return 0;
}

关键特性说明

  • 编译期计算:所有大小判断和实例化均在编译期完成,无运行时额外开销
  • 标准容器兼容:实现随机访问迭代器,支持所有C++标准库算法
  • 透明封装:外部无需关心数组物理分散,操作逻辑与连续数组完全一致
  • 静态内存安全:保留原有固定地址分配,符合单片机内存约束

内容的提问来源于stack exchange,提问作者ATL_DEV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 18:58:15