C++ - 64 位上的SP_DEVINFO_LIST_DETAIL_DATA_W大小
C++ - size of SP_DEVINFO_LIST_DETAIL_DATA_W on 64 bit
在 64 位上,SP_DEVINFO_LIST_DETAIL_DATA_W的大小为 560。不应该是554吗?
typedef struct _SP_DEVINFO_LIST_DETAIL_DATA_W {
DWORD cbSize;
GUID ClassGuid;
HANDLE RemoteMachineHandle;
WCHAR RemoteMachineName[SP_MAX_MACHINENAME_LENGTH];
} SP_DEVINFO_LIST_DETAIL_DATA, *PSP_DEVINFO_LIST_DETAIL_DATA;
cbSize 为 4,ClassGuid 为 16,RemoteMachineHandle 为 8(64 位),RemoteMachineName 为 2*(260+3) (SP_MAX_MACHINENAME_LENGTH 为 MAX_PATH + 3)
所以,4+16+8+2*263=554。为什么 sizeof(_SP_DEVINFO_LIST_DETAIL_DATA_W) 返回 560 ?
您忽略了对齐字段的要求,这对于确保处理器可以有效地访问它们非常重要。 HANDLE 类型为 64 位,8 字节,当您以 x64 为目标时。 因此,RemoteMachineHandle 成员与 8 的倍数的偏移对齐。 这会将其从偏移量 20 移动到偏移量 24,下一个偏移量可被 8 整除。 额外的 4 个字节是填充的,未使用。
这使得结构大小为 4 + 16 + 4 + 8 + 2*263 = 558 字节。
还有一个额外的问题 - 此结构的数组会使句柄再次未对齐。 索引 1 处的元素的句柄偏移量为 558 + 4 + 16 + 4 = 582。 这不是 8 的倍数,成员将再次错位。
因此,编译器在结构的末尾添加了额外的 2 个字节的填充,因此结构的总大小是 8 的倍数。 因此:
Offset Size Member
0 4 cbSize
4 16 ClassGuid
20 4 -
24 8 RemoteMachineHandle
32 526 RemoteMachineName
558 2 -
-------------
560
我猜填充以适应某些成员的对齐要求。但是,我不熟悉这些类型,因此我无法解释此结构的对齐方式。
如果您真的想以最有效的方式打包结构,则可以按大小(递减)对成员进行排序。通常不允许编译器对成员重新排序。
我尝试使用SetupDiGetDeviceInfoListDetail,但大小也错误。 终于我找到了解决方案
这是结构体的定义
typedef struct _SP_DEVINFO_LIST_DETAIL_DATA {
DWORD cbSize;
GUID ClassGuid;
HANDLE RemoteMachineHandle;
TCHAR RemoteMachineName[SP_MAX_MACHINENAME_LENGTH];
} SP_DEVINFO_LIST_DETAIL_DATA, *PSP_DEVINFO_LIST_DETAIL_DATA;
在设置中API.h
#define SP_MAX_MACHINENAME_LENGTH (MAX_PATH + 3)
https://msdn.microsoft.com/en-us/library/cc249520.aspx
MAX_PATH 0x00000104
那里为
[StructLayout(LayoutKind.Sequential,Pack = 1, CharSet = CharSet.Ansi)]
public struct SP_DEVINFO_LIST_DETAIL_DATA
{
public uint cbSize;
public Guid classGuid;
public int RemoteMachineHandle;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 263)]public string RemoteMachineName;
};
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- C++中带有List类的迭代器Segfault
- 使用"std::unordereded_map"映射到"std::list"对象
- GCC对可能有效的代码抛出init list生存期警告
- 使用std::list创建循环链表
- 重载Singly Linked List中的赋值运算符
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- "std::list::splice(std::const_iterator pos, std::list&& other)"是否保证将"其他"留空?
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- QStringList vs list<shared_ptr<QString>> 性能比较C++
- 包含 std::list 的结构体的 C++ 初始化
- 在C++中使用 Catch 测试框架编译错误"error: expected ';' at end of declaration list"
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- 在基于范围的 for 循环期间插入 std::list 的后面
- 循环挂起迭代的 std::擦除 on std::list
- 如何增加以前由新运算符分配的 C++ std::list 数组的大小?