许多C / C ++编译器(包括gcc和clang)都具有称为打包结构的功能。由于许多原因,它派上用场,但必须谨慎使用。一个潜在的陷阱是,您将指向结构成员的指针用作另一个函数的参数。现在,该函数不知道未对齐的指针。让我用一些代码说明一下我的意思:
#pragma pack(1)
typedef struct { int x; } uas;
#pragma pack()
void foo(int *f) {
// some code using the value of *f
}
void bar(uas *b) {
foo(&(b->x));
}
Run Code Online (Sandbox Code Playgroud)
int在32位计算机上的对齐方式通常为4。foo()如果f没有4字节对齐,则编译器现在可能会为此生成代码。在较旧的ARM体系结构中就是这种情况。
现在struct uas和其中的所有成员都具有1的对齐保证。显然,传递b->xto 的地址foo()是一个坏主意。
GCC和clang具有编译器警告(-Wcast-align),例如,通过将其转换char*为来触发该警告int*。使用指向压缩结构成员的指针,即使两者都支持,似乎也不会触发此警告。我也试过-Wall和-Wextra,但他们甚至不包括-Wcast-align。
我的主要问题是GCC,clang或任何其他支持打包结构的编译器是否有警告,该警告将由上述特定示例触发。看起来,如果编译器支持压缩结构,则必须发出这样的警告。
我正在尝试使用 Visual Studio 2019 为 Windows XP 编译应用程序。为此,我尝试使用平台工具集 v140_xp。它不起作用,出现以下错误消息:
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\Win32\PlatformToolsets\v140_xp\Toolset.targets(36,5): warning MSB8003: Could not find WindowsSdkDir_71A variable from the registry. TargetFrameworkVersion or PlatformToolset may be set to an invalid version number.
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppBuild.targets(366,5): warning MSB8003: Could not find WindowsSDKDir variable from the registry. TargetFrameworkVersion or PlatformToolset may be set to an invalid version number.
Run Code Online (Sandbox Code Playgroud)
显然,这些工具正在寻找 Windows SDK v7.1A。从 Microsoft 下载 Windows 7 SDK 不起作用。即使您设法安装它,SDK 也有 7.1 版(没有 A)而不是 7.1A。所以错误仍然存在。
我发现 Windows SDK v7.1A 曾经包含在 Visual Studio 2015 …