字节对齐、sizeof和strlen
小端模式:数据的高字节放在内存的低地址,数据的低字节放在内存的高地址。记住:小端模式是相反的,只需要记住小端模式即可,windows默认采用的是小端模式。
字节对齐问题:字节对齐有3个准则:
1.结构体变量的首地址能被其最宽的基本类型成员的大小所整除;
2.结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如果需要,编译器会在成员之间加上填充字节;
3.结构体的总大小为结构体最宽基本类型成员大小的整数倍,如果有需要,编译器会在最后一个成员后面加上填充字节。
例如下面的一个程序,结构体内的数据成员类型相同,只是顺序改变,则占用的内存不同:
1 #include<iostream> 2 using namespace std; 3 4 struct A 5 { 6 char a; 7 int b; 8 short c; 9 float d; 10 double e; 11 }; 12 13 struct B 14 { 15 short b; 16 double e; 17 short c; 18 float d; 19 char a; 20 }; 21 22 23 int main() 24 { 25 cout<<"sizeof(A):"<<sizeof(A)<<endl; 26 cout<<"sizeof(B):"<<sizeof(B)<<endl; 27 28 return 0; 29 }
程序的运行结果:
sizeof(A):24
sizeof(B):32
分析:
A:char a首地址为0,则0+1=1,而根据第二条,int b的首地址必须是4的整数倍,则需要字节填充,int b的首地址是4;同理short c的首地址为8,float d的首地址为12,double e的首地址为16,总共的字节数为24,正好是最长的字节数double e的整数倍(24是8的整数倍),所以最终的sizeof(A)=24;
B:short b的首地址为0,double e的首地址为8,short c的首地址为16,float d的首地址为20,char a的首地址是24,则总共的字节数是25,不符合第三条规定(25不能被8整除),所以需要凑整变成32,则最后sizeof(B)=32.
在内存中,struct和union是要考虑内存中字节对齐问题的,但它们之间又有一些区别。struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和+考虑到内存对齐所补的字节。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的
strlen函数:
strlen做的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间的某个位置,甚至是某个不确定的内存区域)开始扫描,直至碰到第一个字符串结束符‘\0’为止,然后返回计数器值(长度不包含'\0').
几个关于sizeof和strlen之间区别的例子:
1 #include<iostream> 2 using namespace std; 3 4 int Getsize(char data[]) 5 { 6 return sizeof(data); 7 } 8 9 int main() 10 { 11 char* ss="0123456789"; 12 13 cout<<"sizeof(ss):"<<sizeof(ss)<<endl; //结果是4,ss是指针 14 cout<<"sizeof(*ss):"<<sizeof(*ss)<<endl; //结果是1,*ss=ss[0],是首字符 15 cout<<"sizeof('0123456789'):"<<sizeof("0123456789")<<endl;//结果是11,还要加上结束符'\0' 16 cout<<"strlen(ss):"<<strlen(ss)<<endl; //结果是10,不需要加上结束符'\0' 17 18 19 char str[10]={"hello"}; 20 char* pstr=str; 21 cout<<"sizeof(str):"<<sizeof(str)<<endl; //10 22 cout<<"sizeof(pstr):"<<sizeof(pstr)<<endl; //4 23 cout<<"strlen(str):"<<strlen(str)<<endl; //5 24 cout<<"strlen(pstr):"<<strlen(pstr)<<endl; //5 25 26 cout<<"Getsize(str):"<<Getsize(str)<<endl; //4,str从实参传到形参时退化为同类型的指针 27 28 return 0; 29 }