面试题答案
一键面试内存对齐
不同操作系统可能有不同的默认内存对齐方式。通过 #pragma pack
指令可以调整结构体的内存对齐方式。
Windows
在Windows下,通常使用 #pragma pack
来指定对齐方式。例如,指定对齐为4字节:
#pragma pack(push, 4)
struct MyStruct {
char a;
int b;
short c;
};
#pragma pack(pop)
#pragma pack(push, 4)
表示将当前对齐方式压入栈,并设置新的对齐方式为4字节。#pragma pack(pop)
则恢复之前的对齐方式。
Linux 和 macOS
在Linux和macOS下,GCC提供了 __attribute__((packed))
来实现类似功能,但也可以使用 #pragma pack
兼容代码。例如:
#pragma pack(push, 1)
struct MyPackedStruct {
char a;
int b;
short c;
} __attribute__((packed));
#pragma pack(pop)
这里 __attribute__((packed))
强制结构体按1字节对齐,#pragma pack
指令提供了跨平台兼容性。
特定平台的函数调用约定
Windows
Windows下常见的函数调用约定有 __stdcall
和 __cdecl
。__stdcall
由被调用者清理栈,__cdecl
由调用者清理栈。例如:
#ifdef _WIN32
__declspec(dllexport) int __stdcall MyFunction(int a, int b) {
return a + b;
}
#endif
__declspec(dllexport)
用于导出函数,__stdcall
指明调用约定。
Linux 和 macOS
在Linux和macOS(基于Unix系统)下,通常使用标准的C调用约定,不需要特别的修饰符。但如果要兼容Windows风格的调用约定,可以使用GCC的扩展:
#ifdef __linux__ || defined(__APPLE__)
int MyFunction(int a, int b) {
return a + b;
}
#endif
对于特定的调用约定需求,GCC也支持类似 __attribute__((stdcall))
这样的扩展,但这不是标准做法。
综合跨平台代码示例
#ifdef _WIN32
#pragma pack(push, 4)
__declspec(dllexport) int __stdcall MyFunction(int a, int b) {
return a + b;
}
#pragma pack(pop)
#elif defined(__linux__) || defined(__APPLE__)
#pragma pack(push, 1)
int MyFunction(int a, int b) {
return a + b;
}
#pragma pack(pop)
#endif
这个示例展示了如何使用 #pragma
指令以及条件编译来处理不同平台间内存对齐和函数调用约定的差异。