I'm calling a 3rd-party C99 library from modern C++. The API contains a struct that ends with a flexible array member. To allocate the struct on the stack I think I need a byte buffer then cast it to the struct.
Is my use of reinterpret_cast
well-defined (i.e., is not undefined behavior)?
#include <cstddef>
#include <print>
// 3rd-part C99 API
extern "C" {
struct Foo {
int length;
int array[];
};
void do_something(struct Foo*);
}
// My C++ code
auto bar() {
auto length = 4;
std::byte buffer[sizeof(Foo) + length * sizeof(int)];
auto &foo = *reinterpret_cast<Foo *>(buffer); // ← Is this UB?
foo.length = length;
do_something(&foo); // ← Is this UB?
std::println("Result: {}", foo.array[3]); // ← Is this UB?
}
Edit: I'm compiling with -std=gnu++23
so flexible array members will compile.
IMO it is UB. But you can do something like this (VLAs are not portable in C++ and it is gcc-centric):
#include <cstddef>
#include <new>
#include <print>
extern "C" {
struct Foo {
int length;
int array[]; // non-portable C++ extension
};
void do_something(struct Foo*);
}
auto bar() {
int length = 4;
// Ensure proper alignment for Foo
alignas(Foo) std::byte storage[sizeof(Foo) + length * sizeof(int)];
// Create a Foo object in that storage
auto* foo = std::construct_at(reinterpret_cast<Foo*>(storage));
foo->length = length; // initialize header before calling C
do_something(foo); // now OK (alignment + lifetime are fine)
// OK if do_something wrote at least 4 ints
std::println("Result: {}", foo->array[3]);
std::destroy_at(foo); // trivial, but symmetric
}
https://godbolt.org/z/Kr5zxfqWj
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With