• 利用宏定义在编译阶段检查结构体大小的方法


    1、宏定义

    //检查结构体dataType的大小是不是nBytes字节,如果不是则编译报错
    #define CHECK_SIZE_TYPE(dataType, nBytes) \
    							typedef char SC_EQ_##dataType[(sizeof(dataType) == (nBytes)) ? 1 : -1]
    
    • 1
    • 2
    • 3

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    (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 
    
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    #pragma pack是强行修改对齐字节数,如果不清楚可以参考博客:《嵌入式开发——#pragma pack()常见用法介绍》

  • 相关阅读:
    多进程与多线程 - 概述
    ShapeableImageView 的使用,告别shape、三方库
    骑行适合戴什么耳机,分享五款最适合骑行的运动耳机
    C和指针 第15章 输入/输出函数 15.4 ANSI I/O概念
    DBnet检测加分类,提取身份证要素
    ABC341A-D题解
    初识Thymeleaf
    css的布局方式
    Web3 的通行证——DID 带来数字身份革命
    每个人都应该去学写作
  • 原文地址:https://blog.csdn.net/weixin_42031299/article/details/126789802