1、宏定义
//检查结构体dataType的大小是不是nBytes字节,如果不是则编译报错
#define CHECK_SIZE_TYPE(dataType, nBytes) \
typedef char SC_EQ_##dataType[(sizeof(dataType) == (nBytes)) ? 1 : -1]
2、宏定义原理分析
//下面的结构体,在32位的机器中占12字节,在64位的机器中占16字节
typedef struct
{
char a; //占1字节
long long b; //占8字节
}testType;
//结构体大小如果不是16字节就报错,也就是程序如果不在64位的机器上运行就报错
CHECK_SIZE_TYPE(testType, 16);
//将上面的宏定义展开,定义了名字为SC_EQ_testType的数组
//数组的元素个数根据"(sizeof(testType) == (16)"是否成立来决定,如果成立则元素个数为1,不成立元素个数为-1
//如果数组的元素个数为-1就会报错,编译就不会通过
typedef char SC_EQ_testType[(sizeof(testType) == (16)) ? 1 : -1]
//如果"(sizeof(testType) == (16)"成立
typedef char SC_EQ_testType[1]
//如果"(sizeof(testType) == (16)"不成立
typedef char SC_EQ_testType[-1]
(1)在不同位数的机器中,结构体默认的对齐字节数不同:32位机器默认4字节对齐,64位机器默认8字节对齐;
(2)testType结构体在32位的机器中占12字节,在64位的机器中占16字节,原因就是默认的对齐字节数不同,这里不详细分析;
(3)CHECK_SIZE_TYPE(testType, 16):在编译的时候检测testType结构体大小是否是16字节,如果不是则编译报错;
(4)上面用CHECK_SIZE_TYPE宏去检测testType结构体,保证了程序只能在64位的机器上运行,因为32位的机器在编译的时候就通过不了;
3、测试代码
#include <stdio.h>
#define CHECK_SIZE_TYPE(dataType, nBytes) \
typedef char SC_EQ_##dataType[(sizeof(dataType) == (nBytes)) ? 1 : -1]
#pragma pack(push)
//#pragma pack(8) //模拟64位CPU的情况,按8字节对齐
#pragma pack(4) //模拟32位CPU的情况,按4字节对齐
typedef struct
{
char b;
long long a;
}testType;
#pragma pack(pop)
//确保程序在64位CPU上运行
//CHECK_SIZE_TYPE(testType, 16);
//确保程序在32位CPU上运行
CHECK_SIZE_TYPE(testType, 12);
int main(int argc, char *argv[])
{
printf("sizeof(testType)=%d\n", sizeof(testType));
return 0;
}
#pragma pack是强行修改对齐字节数,如果不清楚可以参考博客:《嵌入式开发——#pragma pack()常见用法介绍》;