在 C++ 中是否有与 C# Structs/StructLayout 具有字段偏移的等效功能?

Ben*_*Ben 5 c# c++

以 C# 结构体为例:

    [StructLayout(LayoutKind.Explicit)]
    public struct Example
    {
        [FieldOffset(0x10)]
        public IntPtr examplePtr;

        [FieldOffset(0x18)]
        public IntPtr examplePtr2;

        [FieldOffset(0x54)]
        public int exampleInt;
    }
Run Code Online (Sandbox Code Playgroud)

我可以获取一个字节数组,并将其转换为这个结构,如下所示:

    public static T GetStructure<T>(byte[] bytes)
    {
        var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        var structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        handle.Free();
        return structure;
    }

    public static T GetStructure<T>(byte[] bytes, int index)
    {
        var size = Marshal.SizeOf(typeof(T));
        var tmp = new byte[size];
        Array.Copy(bytes, index, tmp, 0, size);
        return GetStructure<T>(tmp);
    }

    GetStructure<Example>(arrayOfBytes);
Run Code Online (Sandbox Code Playgroud)

C++ 中是否有等效的功能来获取字节数组并将其转换为结构,其中并非所有字节都用于转换(C# structlayout.explicit w/field offsets)?

希望做像下面这样:

struct {
  pad_bytes[0x10];
  DWORD64 = examplePtr;
  DWORD64 = examplePtr2;
  pad_bytes2[0x44];
  int exampleInt;
}
Run Code Online (Sandbox Code Playgroud)

mpo*_*ter 0

不,我不知道指定某些结构成员的字节偏移量的方法 - 标准中肯定没有任何内容,而且我不知道任何编译器特定的扩展。

除了填充成员(正如您已经提到的)之外,您还可以使用alignas, #pragma pack, and __declspec(align(#))(在 MSVC 上)和__attribute__ ((packed))and __attribute__ ((aligned(#)))(在 GCC 上)。当然,这些不允许您指定偏移量,但它们可以帮助控制结构的布局。

我能想到的确保您的布局符合您的期望的最好方法是static_assert使用offsetof

struct Example{
  char pad_bytes[0x10];
  DWORD64 examplePtr;
  DWORD64 examplePtr2;
  char pad_bytes2[0x44];
  int exampleInt;
};
static_assert(offsetof(Example, examplePtr) == 0x10);
static_assert(offsetof(Example, examplePtr2) == 0x18);
static_assert(offsetof(Example, exampleInt) == 0x54);
Run Code Online (Sandbox Code Playgroud)