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

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()常见用法介绍》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第十二章 自定义数据类型 12.1 结构体 结构体(structure)又叫结构,是一种构造类型,由若干成员构成,成员可以是一个基本数据类型或一个构造类型。 12.1.1 结构体声明 声明结构体的形式: struct 结构名 { 成员表列; }; 成员表列由若干个成员组成,每个成员必须做类型说明,形式为: 类型说明符 成员名; 例1:声明学生结构: struct student { int iNum; char cArrName[20]; char cSex; float fScore; }; 注意不要忘记}后的分号(;)。 成员名可与程序中其他变量同名,互不干扰。 结构体声明并不分配空间,结构体声明是在说明一种数据类型,不是变量定义。例1中结构体student与int、float一样都是数据类型。 声明结构体后可定义结构体变量,这时分配空间。 12.1.2 结构体变量定义 声明结构体后可以定义结构体变量。 定义方法: a.先声明结构体,再定义结构体变量 struct student { int iNum; char cArrName[20]; char cSex; float fScore; }; struct student stu1,stu2; 可以用宏定义使用一个符号常量表示一个结构体类型。 b.在声明结构体同时定义结构体变量 struct student { int iNum; char cArrName[20]; char cSex; float fScore; }stu1,stu2; c.直接定义结构体变量 struct { int iNum; char cArrName[20]; char cSex; float fScore; }stu1,stu2; 第三种与第二种区别在于省去了结构体类型名,而直接给出结构体变量。这种方法结构体只能用一次,即使再声明成员完全相同的结构体类型,也和此次定义的结构体类型属于不同的结构体类型。 结构体变量在内存空间中是连续存储的,结构体类型大小为sizeof(struct student),为各成员大小之和,各编译系统为内存管理方便可能分配大一些的内存空间来存储结构体,保证字节对齐。在Dev中上述结构体类型student为32字节。 结构体成员可以又是一个结构体,即构成嵌套的结构体。如: struct date { int year; int month; int day; }; struct student { int iNum; char cArrName[20]; char cSex; float fScore; struct date birthday; }; 12.1.3 结构体变量引用 1.结构变量初始化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值