C++字节基础

本文主要介绍了C++中的字节序和字节对齐知识。阐述了VS和Linux的默认对齐值,介绍了自身对齐值、指定对齐值、有效对齐值等概念及结构体字节对齐规则,并通过多个例子详细说明。还提及了枚举的内存共享情况,最后给出相关练习链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、字节序

bool am_little_endian ()
{
unsigned short i=1;
return (int)*((char *)(&i)) ? true : false;
}
int main()
{
if(am_little_endian())
{
printf("本机字节序为小段序!\n");
}else
{
printf("本机字节序为大段序!\n");
}
return 0;
}

二、字节对齐

VS默认8,Linux默认4。

结构体字节对齐规则
先介绍三个概念:自身对齐值、指定对齐值、有效对齐值。

a: 自身对齐值:数据类型本身的对齐值,例如char类型的自身对齐值是1,short类型是2;

b: 指定对齐值:编译器或程序员指定的对齐值,32位单片机的指定对齐值默认是4;

c: 有效对齐值:自身对齐值和指定对齐值较小 的那个。

自定义类型的自身对齐值:自定义类型中对齐值最大的值

对齐有两个规则:

d: 不但结构体的成员有有效对齐值,结构体本身也有对齐值,这主要是考虑结构体的数组,对于结构体或者类,要将其补齐为其有效对齐值的整数倍。结构体的有效对齐值是其最大数据成员的自身对齐值

e: 存放成员的起始地址必须是该成员有效对齐值的整数倍。

例子一:

#pragma pack (2)
	typedef struct head {
		char f
	} _head;
#pragma pack ()
	int a = sizeof(_head);//a = 1

假如结构体起始地址是0x0000,

成员f的自身对齐值1,指定对齐值2,所以有效对齐值是1,根据规则e地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;

根据规则d,体结构体本身也有对齐值,是其最大数据成员的自身对齐值。所以这里是成员f,体结构体本身对齐值是1。再根据e,1是1的整数倍,所以结构体大小为1。

例子二:

#pragma pack (2)
	typedef struct head {
		char f  //1+1
		int b; //4
		char c;//1+1
	} _head;//1+1 + 4 + 1+1 = 8
#pragma pack ()
	int a = sizeof(_head);//a = 8

假如结构体起始地址是0x0000

成员f的自身对齐值1,指定对齐值2,所以有效对齐值是1,根据规则e,地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;

成员b的自身对齐值4,指定对齐值2,所以有效对齐值是2,根据规则e,地址0x0002是2的整数倍,故a存放起始地址是0x0002,占4个字节;

成员c的自身对齐值1,指定对齐值2,所以有效对齐值是1,根据规则e,地址0x0006是1的整数倍,故a存放起始地址是0x0006,占一个字节;

此时共用了7个字节,但是根据规则d,体结构体本身也有对齐值,是其最大数据成员的自身对齐值。所以这里是成员b,体结构体本身对齐值是4。再根据e,7不是4的整数倍,所以要+1,,即为8。

例子三:

#pragma pack (16)
	typedef struct head {
		char f //1+3
		int b;//4
		char e;//1+3
	} _head;//all = 12
#pragma pack ()
	_head h;
	int a = sizeof(h);  //a = 12

假如结构体起始地址是0x0000

成员f的自身对齐值1,指定对齐值16,所以有效对齐值是1,根据 规则e 地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;

成员b的自身对齐值4,指定对齐值16,所以有效对齐值是4,规则e 地址0x0004是4的整数倍,故a存放起始地址是0x0004,占4个字节;

成员c的自身对齐值1,指定对齐值16,所以有效对齐值是1,规则e 地址0x0008是1的整数倍,故a存放起始地址是0x0008,占一个字节;

此时共用了9个字节,但是根据规则d,体结构体本身也有对齐值,是其最大数据成员的自身对齐值。所以这里是成员b,体结构体本身对齐值是4。再根据e,9不是4的整数倍,所以要+3,,即为12。

例子四:

#pragma pack (8)
typedef struct Test
{
	short a; //2 +6
	struct Inner
	{
		int b; //4 +4
		double c; //8
		long d; //4 +4
	};
	int e; //4 +4
}Test;

void main()
{
	printf("%d\n", sizeof(Test)); //40
}

struct Inner 有效对齐字节是8

#pragma pack (8)
typedef struct Test
{
  short a;//2 + 6
  struct
  {
     int b;//4 +4
     double c[10];//80
     char d;//1+7
  };
  int e;//4
}Test;  //  sizeof  == 112

同样int b不能按80对齐,而是按照double 本身的字节大小8对齐
double c[10];//80 有效字节数是8

#pragma pack (8)
struct S1
{
	char a;//1+7
	double b;//8
	int c;//4+4
};//24
struct S2
{
	char a;//1+3
	int c;//4
	double b;//8
};//16

有枚举的

#pragma pack (8)

union Un1
{
	short c[6];
	double i;
};
union Un2
{
	short c[6];
	int i;
};
struct S1
{
	char c;//1+7
	Un1 r1;//16
};
struct S2
{
	char c;//1+3
	Un2 r2;//12
};

枚举共享内存,所以是内存是最大的那个,Un1是short c[7];Un2是short c[6];,
Un1中最大成员字节是double ,是8,所以Un1字节是12+4 = 16
Un12中最大成员字节是int,是8,所以Un2字节是12

Un1 最大对齐是double也就是8,所以S1字节是1+7+16 = 24
Un2 最大对齐是double也就是4,S2字节是1+3+16 = 16

练习

https://blog.csdn.net/qq_51681435/article/details/110394111

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值