5.10 Passing Arrays by Reference (int(&)[N]) vs C++20 std::span in Embedded APIs
Executive Summary: Passing fixed arrays by reference (int(&)[N]) to prevent pointer decay. We analyze template-based array references and modern C++20 std::span for zero-overhead, non-owning contiguous memory views.
💻 1. Annotated Source Code
#include <iostream> #include <array> using namespace std; int productArray(array<int, 6> myArray); void productArray(array<int, 6> myArray, int& result); int main() { array<int, 6> numbers{ 1, 2, 3, 4, 5, 6 }; int finalProduct; productArray(numbers, finalProduct); cout << "The product of the array elements (by reference) is: " << finalProduct << endl; /*int result = productArray(numbers); cout << "The product of the array elements is: " << result << endl;*/ return 0; } int productArray(array<int, 6> myArray) { int product = 1; for (int num : myArray) { product *= num; } return product; } void productArray(array<int, 6> myArray, int& result) { result = 1; for (int num : myArray) { result *= num; } }
📐 2. Architecture & UML Class Model
<<compilation-unit>>
ProductReferenceEngine
Reference Pipeline
Attributes / Data Members
(none / stateless)
Operations / Methods
+computeArrayProduct(arr: const int*, size: size_t, productOut: int64_t&) : void
📚 3. Core C++ Concepts Deep-Dive
1. Passing Arrays by Reference Syntax
Writing void compute(int (&arr)[5]) passes the array by reference without decay. The compiler strictly enforces that only arrays of exactly length 5 can be passed.
2. C++20 std::span
std::span<T> is a lightweight non-owning view over any contiguous sequence of elements (pointer + size, 8 bytes total on 32-bit MCU).
⚡ 4. Embedded Systems & Hardware Reality
1. Unified Buffer Passing with std::span
In driver development, std::span<const uint8_t> can accept a C array, a std::array, or an RTOS buffer seamlessly with zero copying.
💡 5. Production-Ready Embedded Refactoring
Clean driver buffer API using std::span:
💡 Production-Ready Refactor
#include <cstdint> #include <numeric> // Non-decaying template array reference template <typename T, size_t N> T computeProduct(const T (&arr)[N]) noexcept { T product = 1; for (size_t i = 0; i < N; ++i) { product *= arr[i]; } return product; }
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.
Q1. What is the key advantage of passing an array by reference using 'void func(int (&arr)[10])'?
Detailed Explanation:
Array references (
(&arr)[N]) retain full array size metadata and cause compilation to fail if an array with different bounds is passed.
Q2. What is C++20 std::span?
Detailed Explanation:
std::span represents a contiguous sequence of objects without owning the memory, encapsulating a pointer and length in a compact 8-byte structure.
Q3. Does passing a std::span<uint8_t> copy the underlying array buffer?
Detailed Explanation:
std::span is a non-owning view; passing it passes only the pointer and length, performing zero buffer copying.
Q4. Can std::span prevent buffer overflows in embedded drivers?
Detailed Explanation:
std::span retains element counts, enabling safe range-based iteration and bounded slicing.