Question Details

No question body available.

Tags

c++ language-lawyer ffi

Answers (17)

April 4, 2026 Score: 5 Rep: 122,888 Quality: Medium Completeness: 50%

"does not work because of the strict aliasing rules"

Strict aliasing rules are about accessing an object via a reference to another type of object. They are not about the type of pointer or reference that is used to pass an address around without accessing the actual object. If you know that there is an array of T at that address, you can cast the pointer you have to T* and use it. It does not matter one bit what the type of the pointer is.

April 4, 2026 Score: 2 Rep: 104,474 Quality: Low Completeness: 30%

Is this a practical question or a language-theoretical one? In practice you just reinterpret_cast. If the bytes come from an opaque source, this is entirely fine.

April 4, 2026 Score: 2 Rep: 2,684 Quality: Low Completeness: 60%

There is also std::bitcast (C++20) and std::startlifetimeas (C++23).

April 5, 2026 Score: 1 Rep: 122,888 Quality: Low Completeness: 50%

There is no inherent undefined behavior in reinterpret_cast (why would it be in the language otherwise?)

The standard says something like this:

An object pointer can be explicitly converted to an object pointer of a different type... (Note: Converting a pointer of type “pointer to T1” that points to an object of type T1 to the type “pointer to T2” (where T2 is an object type and the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value).

April 5, 2026 Score: 1 Rep: 74,553 Quality: Low Completeness: 30%

This is the use case for reinterpret_cast. This is what it's for. Use it.

April 5, 2026 Score: 1 Rep: 1,121 Quality: Low Completeness: 40%

You're not trying to access it through a byte array though. You're trying (or should be trying) to access it through its own reference, of type T&. There's not even any byte array involved, only a pointer (of some different type, whether that's std::byte or void or yourmum* doesn't matter) that holds an address.

April 4, 2026 Score: 1 Rep: 612,019 Quality: Low Completeness: 50%

Why are you passing a copy of the object to Rust, and then passing that copy back to C++? Why not just pass around a pointer to the original object instead?

IOW, given a T object, get a T pointer to it, convert that pointer into the byte array, pass it around, and then convert the byte array back into a T to access the original T.

T obj; ... T ptrObj = &obj; std::byte arr[sizeof(ptrObj)]; memcpy(arr, &ptrObj, sizeof(ptrObj)); ... std::byte ptr = ...; T* pObj; memcpy(&pObj, ptr, sizeof(pObj)); // use pObj as needed...
April 4, 2026 Score: 1 Rep: 3,592 Quality: Low Completeness: 40%

The object is passed to Rust from C++ and opaquely passed around by Rust code and then passed back to C++ again, so whatever invariant it holds it remains. In other words I’m sure the bytes contain a valid representation of a value of type T, I just need to get back a valid pointer of that type.

April 4, 2026 Score: 1 Rep: 5,530 Quality: Low Completeness: 40%

Is the T that is in the std::byte array guaranteed to be properly aligned?

How did the T get into the std::byte array in the first place?

What if the T has something like a std::string, which is special purpose smart pointer for doing string things. How is that kind of T handled?

April 4, 2026 Score: 1 Rep: 37,331 Quality: Low Completeness: 40%

In principle you are right to be concerned about it.

But in practice FFI (where you "breach" the language barrier) is a typical case where sometimes you have to violate the strict requirements regarding UB, reinterpret_cast etc.

I believe no reasonable compiler will hold that against you ... (i.e. in practice it will behave as you expect - assuming the bytes are really a valid C++ object).

April 4, 2026 Score: 1 Rep: 3,592 Quality: Low Completeness: 30%

Ah no, it works only for ImplicitLifetimeType types...

April 4, 2026 Score: 0 Rep: 3,592 Quality: Low Completeness: 0%

Hm, both, I mean, I don’t want to write code that breaks with version N+1 of a compiler.

April 4, 2026 Score: 0 Rep: 3,592 Quality: Low Completeness: 40%

Thanks! I didn't include std::bitcast because it only works for trivially copyable types.

Instead I didn't know about std::startlifetime_as! It solves the problem apparently, doesn't it?

April 4, 2026 Score: 0 Rep: 3,592 Quality: Low Completeness: 0%

Thanks! I’m not sure the argument is convincing though, do you have any source or reference?

April 4, 2026 Score: 0 Rep: 1,121 Quality: Low Completeness: 60%

reinterpretcast is the good ol' way to do what you need since it doesn't actually do anything with the object, just tells the compiler that yes, this address in memory corresponds to an object of type T. Consider the code

auto *ptr = std::reinterpretcast(&oldvalue);
auto &newvalue = std::reinterpret_cast(ptr);

Nothing happened. We defined some variables but if they're not used, this is just a no-op and if only new_value is used, it's clear that new_value is a reference to old_value and it's as if ptr didn't exist. There's no flow of data involved, only compiler abstractions that will be worked into lower-level (assembly etc) abstractions as one and the same address. It doesn't make sense for this to be UB.

C++ is very permissive. As long as you make sure that your code makes sense, the fact that someone else could make a mistake trying something similar is irrelevant. You're not allowed to contradict yourself and there are some things left as UB because they don't really make sense, but under all the assurances you give, just working with an object that really lives at an address is perfectly fine.

However, you shouldn't be returning T by value since that's making a copy. The return type of std::reinterpret_cast is T & and you actually want a reference as you're just referring to an existing object.

April 5, 2026 Score: 0 Rep: 3,592 Quality: Low Completeness: 40%

You can convert the pointers but accessing them may be UB if some conditions are not satisfied. The cppreference page says:

If a program attempts to read or modify the stored value of an object through a glvalue through which it is not type-accessible, the behavior is undefined.

And “type accessible” means things, but as far as I can tell, an object of arbitrary type is not type-accessible through a byte array.

Am I misunderstanding anything?

April 5, 2026 Score: 0 Rep: 122,888 Quality: Low Completeness: 0%

Have you read the definition of type accessibility? Anything is type-accessible through a byte array. But this is irrelevant, since you are not even trying to do that, as @Xellos notes.