gpt4 book ai didi

c - 如何使用#pragma pack(1) OR/Zp1 以便它们单独影响应用程序定义结构的打包,而不影响 Windows SDK 中定义的结构?

转载 作者:太空宇宙 更新时间:2023-11-04 03:11:45 29 4
gpt4 key购买 nike

我正在将我的应用程序(win32 和 MFC 的混合体)移植到 Visual Studio 2017 (x64) 使用 VC98(使用命令行上的 makefile 构建,而不是 IDE)(x86) 编译。该应用程序使用了大量的 C 结构,这些结构与数据一起打包,复制到缓冲区并通过 N/W 发送。通信协议(protocol)要求这些结构完全没有额外的填充,以便发送的数据符合用于客户端(我的应用程序)和服务器的通信规范。为确保这一点,应用程序使用/Zp 来编译每个文件。

在使用/Zp(从 IDE)移植到 VS2017 (x64) 后,当我尝试运行应用程序时,应用程序 GUI 没有启动,并且当某些 SDK/MFC 定义的结构是由应用程序访问,例如 OPENFILENAME。因此,为了解决这个问题,在 VS2017 中仍然在项目级别定义/Zp 的情况下,我在包含 windows.h 的地方使用了以下内容:

#ifdef _WIN64
#pragma pack(push,8)
#endif
#include <windows.h>
#ifdef _WIN64
#pragma pack(pop)
#endif

这在一定程度上解决了这个问题,但我仍然从 MFC 中得到一些错误,一些功能如 crypt API (MSCAPI) 不起作用,这可能是因为我的应用程序包含其他头文件,如 windows.h,它们也需要像上面一样受到保护。

作为替代方案,我也尝试过完全不使用/Zp,然后转到每个头文件并将文件的全部内容(在系统头文件包含之后)包含在 #pragma pack(1) 之间和#pragma pack()。这可行,但并非万无一失,而且对我来说对 1000 个头文件做同样的事情太乏味了。

因此,简而言之,我需要一种方法来确保我的应用程序定义的所有 C 结构不使用任何填充,但 Windows SDK/MFC 定义的结构继续使用默认填充(可能是 8 个字节)。关于如何以最少的更改以万无一失的方式解决此问题的任何想法?也许,这个问题不会出现在 VC98 中,因为平台是 x86,或者 VC98 附带的 SDK 没有对结构的打包做出任何假设。

最佳答案

通过网络或通过文件传输二进制结构数据是一种非常脆弱的方法:

  • 只要 struct 定义中使用的类型保持相同的表示形式,打包结构只能解决对齐问题。检查结构中使用的低级类型的定义:LONG 在 64 位 Windows (!) 上仍然是 32 位的,但 size_t 具有不同的大小。
  • 不同机器的字节顺序可能不同:x86 使用小端表示法,而手机或平板电脑中使用的其他一些处理器可能使用大端法。无法在内存中强制执行特定的字节顺序。
  • 强制结构成员未对齐可能会在某些处理器上导致未定义的行为,x86 默认配置为非常宽松,这在其他处理器上通常是不可能的。
  • 尽管是硬件之上的非常薄的抽象,C 语言不允许精确控制用于内存结构的实际布局。不可移植映射的一个很好的例子是位域的实现。您的结构可能具有在 32 位 Windows 和 64 位架构上映射不同的位域。

为了解决这些可移植性问题,现代程序不依赖于二进制数据的内部表示,它们一次处理一个成员的结构化数据,以在两端使用特定的表示、大小、字节顺序、位编码。

关于c - 如何使用#pragma pack(1) OR/Zp1 以便它们单独影响应用程序定义结构的打包,而不影响 Windows SDK 中定义的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55682637/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com