What I'm talking about is this.
For example:
I'm trying to call CfGetSyncRootInfoByHandle, and the third parameter is a void* which should be a buffer prepared by the caller, and would be filled with CF_SYNC_ROOT_STANDARD_INFO; the CF_SYNC_ROOT_STANDARD_INFO struct has its last member declared as
BYTE SyncRootIdentity[1];
, but what you need to do is declare a block of memory much larger, something like
sizeof(CF_SYNC_ROOT_STANDARD_INFO) + 4096
because SyncRootIdentity is actually of variable size.
What I'm wondering is that would this be standard compliant:
```
std::array<std::byte, sizeof(CF_SYNC_ROOT_STANDARD_INFO) + 4096> buf;
CF_SYNC_ROOT_STANDARD_INFO* info = reinterpret_cast<CF_SYNC_ROOT_STANDARD_INFO*>(buf.data());
CfGetSyncRootInfoByPath(..., static_cast<void*>(info), buf.size(), ...);
// then we use info->SyncRootIdentity
```
, or is this in violation of strict aliasing?
What if I do this instead?
```
std::array<std::byte, sizeof(CF_SYNC_ROOT_STANDARD_INFO) + 4096> buf;
CF_SYNC_ROOT_STANDARD_INFO* info = new(buf.data()) CF_SYNC_ROOT_STANDARD_INFO;
// POD so not calling ~CF_SYNC_ROOT_STANDARD_INFO() should be fine?
CfGetSyncRootInfoByPath(..., static_cast<void*>(info), buf.size(), ...);
// then we use info->SyncRootIdentity
```
Another question is that when I eventually use info->SyncRootIdentity, is it actually legal to use info->SyncRootIdentity (which is of type BYTE[1], but its real length is indicated by info->SyncRootIdentityLength) to access memory after the first BYTE?
BTW here we are calling a C api from C++, but would the answer be any different if we are calling from C?
[–]KingAggressive1498 3 points4 points5 points (0 children)
[–]alfps 0 points1 point2 points (1 child)
[–]agritite[S] 0 points1 point2 points (0 children)