https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116909
--- Comment #6 from Federico Kircheis <federico at kircheis dot it> --- Thank, I think this covers all my concern. Nevertheless I was still looking how to avoid the assembly, eventually to be sure to have a more portable piece of code (with less ifdefs) between compilers auto get_tests() noexcept { extern const test_signature* const tests_begin[]; extern const test_signature* const tests_end[]; const auto tests_size = ((uintptr_t)(&tests_end) - (uintptr_t)(&tests_begin))/sizeof(test_signature*); auto begin = std::start_lifetime_as_array<test_signature* const>(tests_begin, tests_size); return std::span<test_signature* const>(begin, begin + tests_size); } With the cast to uintptr_t, I can get the size of the non-existent array without UB. With std::start_lifetime_as_array, I can tell the compiler there is an array. I believe with this construct, the assembly should not be necessary anymore (although a more modern compiler is required, as start_lifetime_as_array comes with c++23, and there seem to be no equivalent for C).