Daily bit(e) of C++ | handling C arrays with std::span

Šimon Tóth
2 min readMay 12, 2024

Daily bit(e) of C++ ♻️53, Safely wrapping C-style arrays using C++20 std::span.

Passing data around as C-style arrays might be unavoidable when interacting with legacy code or C APIs. This can lead to errors when keeping track of the array size.

C++20 introduced std::span, a view that can wrap a contiguous memory block in a range interface. This allows us to safely use algorithms and views to process data without copying it into a C++ container.

std::span can also be converted to a std::span of std::byte, giving access to underlying object representation.

#include <cstdint>
#include <span>
#include <vector>
#include <ranges>

size_t read(char* buffer, size_t size);
int get_data(char** buffer, size_t* size);

char buffer[16];
auto view = std::span(buffer);
// Call C API using a wrapped buffer
size_t cnt = read(view.data(), view.size());
// Process a sub-view based on the number of actually read bytes
for (auto v : view.subspan(0, cnt)) {}


char* buff;
size_t length;
int ret = get_data(&buff, &length);
if (ret != 0) { return ret; }
// Wrap a C buffer into a std::span
auto buffer_view = std::span(buff, length);

// std::span works as any other range, e.g. reverse iteration:
for (auto it = buffer_view.rbegin(); it != buffer_view.rend(); ++it) {}
// or combining with views:
for (auto v : buffer_view | std::views::drop(8)) {}


struct Data {
int x;
int y;
};

std::vector<Data> data{{2,3},{1,5},{4,4}};
// Acces the underlying representation:
std::span<std::byte> bytes = std::as_writable_bytes(std::span(data));

Open the example in Compiler Explorer.

--

--

Šimon Tóth

I'm an ex-Software Engineer and ex-Researcher focusing on providing free educational content.