C++入门——sizeof与字节对齐

"本文探讨了C语言中的strlen函数,用于计算以''结尾的字符串长度,与sizeof关键字用于获取内存大小的差异。sizeof不仅可以处理类型和表达式,还能计算结构体和函数的大小,同时介绍了字节对齐规则及其在结构体中的应用。"
摘要由CSDN通过智能技术生成

sizeof

strlen("\0")与sizeof("\0")

strlen("\0") = 0sizeof("\0") = 2

strlen

strlen用来计算字符串的长度,它从内存的某个位置开始扫描,直到碰到第一个字符串结束符’\0’为止,然后返回计数器值

sizeof

sizeof是C语言的关键字,它以字节的形式给出了其操作数的存储大小,操作数可以是一个表达式或括在括号内的类型名,操作数的存储大小由操作数的类型决定

strlen与sizeof的区别
  1. sizeof是运算符(sizeof既是关键字,也是运算符,但不是函数),而strlen是函数。sizeof后如果是类型,则必须加括弧,如果是变量名,则可以不加括弧

  2. sizeof运算符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能够容纳实现所建立的最大对象的字节大小

  3. sizeof可以用类型作为参数,strlen只能用char*作为参数,而且必须是以’\0’结尾的。sizeof还可以以函数作为参数,如int g();,则sizeof(g())的值等于sizeof(int)的值,在32位计算机下,该值为4

  4. 大部分编译程序的sizeof都是在编译的时候计算的,所以可以通过sizeof(x)来定义数组维数。而strlen则是在运行期计算的,用来计算字符串的实际长度,不是类型占内存的大小。

对于结构体,为什么sizeof返回的值一般大于期望值

struct是一种复合数据类型,其构成元素既可以是基本数据类型,如int、double、float、short、char等,也可以是复合数据类型,如数组、struct、union等数据单元

一般而言,struct的sizeof是所有成员对齐后长度相加,而union的sizeof是取最大的成员长度

字节对齐

字节对齐也称为字节填充,它是C++编译器的一种技术手段,主要是为了在空间与复杂度上达到平衡。简单地讲,是为了在可接受的空间浪费的前提下,尽可能地提高对相同运算过程的最少(快)处理。字节对齐的作用不仅是便于CPU的快速访问,使CPU的性能达到最佳,而且可以有效地节省存储空间。

例如,32位计算机的数据传输是4字节,64位计算机的数据传输是8字节,这样,struct在默认情况下,编译器会对struct的结构进行(32位机)4的倍数或(64位机)8的倍数的数据对齐。对于32位机来说,4字节的对齐能够使CPU访问速度提高,如一个long类型的变量,如果跨越了4字节边界存储,那么CPU要读取两次,这样效率就低了。但需要注意的是,如果在32位机中使用1字节或者2字节对齐,不仅不会提高效率,反而会使访问速度降低。

修改对齐条件

在默认情况下,编译器为每一个变量或数据单元按其自然对齐条件分配空间。但是可以通过下面的方法来改变默认的对齐条件

  1. 使用伪指令#pragma pack(n),编译器将按照n个字节对齐
  2. 使用伪指令#pragma pack(),取消自定义字节对齐方式
  3. _attribute((aligned(n)),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐
  4. _attribute((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐
字节对齐的准则

字节对齐的细节和编译器实现相关,但一般而言,满足以下准则:

  1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除
  2. 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍。如有需要,编译器会在成员之间加上填充字节
  3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节

其中的基本类型即char、short、int、float、double这样的内置数据类型,这里说的“数据宽度”就是指其sizeof的大小

由于结构体的成员可以是复合类型,如果一个结构体中包含另外一个结构体成员,那么此时最宽基本成员不是该结构体成员,而是取其基本类型的最宽值。但在确定复合类型成员的偏移位置时,则是将复合类型作为整体看待,即复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度,达到程序优化的目的

指针进行强制类型转换后与地址进行加法运算

假设在32位机器上,在对齐为4情况下,sizeof(long)的结果为4字节,sizeof(char*)的结果为4字节,sizeof(short int)的结果与sizeof(short)的结果都为2字节,sizeof(char)的结果为1字节,sizeof(int)的结果为4字节,由于32位机器上是4字节对齐,以如下结构体为例:

struct A
{
    long num;
    char *name;
    short int data;
    char ha;
    short ba[5];
}*p;

在32位机器下,sizeof(struct A) = 4 + 4 + 2 + 2 + 1 + 3 + 2*5 + 2 = 24字节
p=0x100000,那么p + 0x200 = 0x1000000 + 0x200*24指针加法,加出来的是指针所指类型的字节长度的整数倍,就是p偏移sizeof(*p)*0x200

(ulong)p + 0x200 = 0x1000000 + 0x200经过ulong后,已经不再是指针加法,而变成一个数值加法了

另外(char*)p + 0x200 = 0x1000000 + 0x200*sizeof(char)结果类型是char*

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值