**
strlen()与sizeof()区别、求法及字节对齐问题
**
- 1.c++中,字符串与字符串类区别
- 2.c++中,strlen()与sizeof()区别
- 3.字符串的长度与字节大小的计算
- 4.字符串类的长度与字节大小计算
- 5.常见字节对齐的计算
c++中,字符串与字符串类区别
1.头文件不同,字符串引用 #include
c++中,strlen()与sizeof()区别
0.strlen()在一般情况下都以‘\0’结束.
1.strlen()是函数;sizeof()是运算符.
2.strlen()只能作为char*的参数,且必须以‘\0’结束;sizeof()还可以把函数作为参数.
3.数组作为strlen()的参数时退化为指针;数组作为sizeof()参数时.
4.strlen(),在程序运行时,得出结果值;sizeof()在程序编译时,得出结果值.
5.strlen()求得是字符串数组的实际长度;sizeof()求的得是分配数组空间的大小.
Code
//字符串类
#include<string>
#include<iostream>
using namespace std;
void main()
{
string str = "12345";
string str1;
//strcpy(str1,str);
str1 = str;
str1 = str1+str;
//1234512345
cout<<"str1 = "<<str1<<endl;
//10
cout<<"str1 size = "<<str1.size()<<endl;
//10
cout<<"str1 length = "<<str1.length()<<endl;
//字符串类的sizeof()结果由编译器决定
cout<<"str1 size of="<<sizeof(str1)<<endl;
}
//字符串
#include<iostream>
using namespace std;
void main()
{
char str[] = "12345";
char str1[]="123";
char str2[]="";
//char str2[] = str1;
strcpy(str2,str1);
//123
cout<<"str2 = "<<str2<<endl;
//12312345
cout<<"str1="<<strcat(str1,str)<<endl;
//8
cout<<"str1 strlen()="<<strlen(str1)<<endl;
//不是9,因为在str1定义时,sizeof(str1)为4.
cout<<sizeof(str1)<<endl;
}
#include<iostream>
using namespace std;
int fun()
{
int a= 0;
return a;
}
void main()
{
char ar[20]={1,2,3,4,5,6,9,9};
//8
cout<<"ar strlen="<<strlen(ar)<<endl;
//20
cout<<"ar sizeof()="<<sizeof(ar)<<endl;
//4
cout<<"ar sizeof()="<<sizeof(fun())<<endl;
}
字符串的长度与字节大小的计算
1.不带‘\0’的字符串计算.
#include<iostream>
using namespace std;
void main()
{
char str[]="12345";
//5
cout<<strlen(str)<<endl;
//6
cout<<sizeof(str)<<endl;
}
2.带‘\0’且后面先跟字母时,把’\0’当做一个字符.
#include<iostream>
using namespace std;
void main()
{
char str[]="12345\0asdf";
//5
cout<<strlen(str)<<endl;
//11
cout<<sizeof(str)<<endl;
}
3.带’\0‘且后面是数字,将两个数字转译成一个字符.
#include<iostream>
using namespace std;
void main()
{
char str[]="12345\0123";
//7
cout<<strlen(str)<<endl;
//8
cout<<sizeof(str)<<endl;
}
4.单个字符
#include<iostream>
using namespace std;
void main()
{
char str[]={'a','3','\0','1','2','e'};
//2
cout<<strlen(str)<<endl;
//6
cout<<sizeof(str)<<endl;
}
字节对齐问题
作用
为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理.
重点
1.每个成员的偏移量都必须是当前成员所占内存大小的整数倍,如果不是,编译器会 自动补充字节.
2.当所有成员大小计算完毕后,编译器判断当前结构体大小是否是结构体中最宽的 成员变量大小的整数倍 , 如果不是会在最后一个成员后做字节填充.
3. 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.).
4.Vc,Vs等编译器默认是#pragma pack(8),所以测试我们的规则会正常;注意gcc默认是#pragma pack(4),并且gcc只支持1,2,4对齐.
结构体类型
#include<iostream>
using namespace std;
//规则1
typedef struct AA
{
//4
int id;
// 4不是8的整数倍 (4+4)+8
double weight;
//16是1的整数倍 16 +1
float height;
}A;
//规则2,所求结构体大小(17)是否是结构体中最宽成员(8)的整数倍;字节填充成为24.
void main()
{
//24
cout<<sizeof(A)<<endl;
}
联合体类型
#include<iostream>
using namespace std;
typedef union BB
{
// 4
int id;
// 20
char ar[20];
// 8
double d;
}B;
//20不是8的整数倍,字节填充24
void main()
{
cout<<sizeof(B)<<endl;
}
结构体镶嵌联合体
#include<iostream>
using namespace std;
typedef union BB
{
int id;
char ar[20];
double d;
}B;
typedef struct AA
{
int id;
double weight;
float height;
//(20 +4)+24
B b;
}A;
void main()
{
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
}
结构体镶嵌结构体、联合体
#include<iostream>
using namespace std;
typedef union BB
{
int id;
char ar[20];
double d;
}B;
typedef struct AA
{
int id;
double weight;
float height;
//24
B b;
}A;
typedef struct CC
{
//4
int id;
//4是1的整倍数,4 +3
char weight[3];
// 7不是8的整倍数,(7+1)+8
double height;
//48
A a;
}C;
void main()
{
//48
cout<<sizeof(A)<<endl;
//24
cout<<sizeof(B)<<endl;
//64
cout<<sizeof(C)<<endl;
}
struct内镶嵌结构体两种形式
1、当结构体内部镶嵌的结构体有名字时,把它当成类型处理不占空间,不计算在外面结构体大小里面。
2、当结构体内部镶嵌的结构体没有有名字时,计算在结构体大小里面;且按8字节对齐。
#include<iostream>
using namespace std;
struct Test
{
int a;//4
struct
{
char b;//1
short c;//1+1 +2
double d;//4+4 +8
};
int e;//4
int a;//4
struct aa
{
char b;
short c;
double d;
};
int e;//4
};
void main()
{
cout<<sizeof(struct Test )<<endl;//32
cout<<sizeof(struct Test )<<endl;//16
}
//带有数组类型的类型,一种类型一种类型 计算
#include<stdio.h>
#include<iostream>
using namespace std;
class Test
{
private:
int ar[5];// 20
char str[6];// 26 26+6 +8*10 116 120
double d[10];
long a
};
int mian()
{
Test tt;
//120
cout<<sizeof(tt)<<endl;
}
//继承
#include<stdio.h>
#include<iostream>
using namespace std;
class Test
{
//24
private:
int ar; //4
char str[6]; //4+ 6 +6+8
double d;
};
//
class T
{
//16
private:
int ar; //4+1+3 +8
char str;
double d;
};
//16
class Test1:public Test,T
{
private:
char str[2];//2+2 +4 +8
int ar;
double d;
};
int main()
{
Test tt;
Test1 tt1;
//24
cout<<sizeof(tt)<<endl;
//56
cout<<sizeof(tt1)<<endl;
return 0;
}
指定字节对齐类型
一字节对齐 把所有的相加,不用考虑与1对齐
//设置字节对齐格式
#pragma pack(1)
typedef struct CC
{
int id;
char weight[3];
double height;
}C;
//取消指定对齐,恢复缺省对齐
#pragma pack()
void main()
{
//15
cout<<sizeof(C)<<endl;
}
位域
通过位来计算大小,减小空间的浪费。
特点:
1、位域不能跨字节存储
2、位域不能跨类型存储
3、位域不能超过其类型对应的位数
#include<iostream>
using namespace std;
struct aa
{
char a:1;
char b:1;
char c:1;
};
void main()
{
//1个字节
cout<<sizeof(aa)<<endl;
}
#include<iostream>
using namespace std;
struct aa
{
char a:5;
char b:2;
char c:2;
};
void main()
{
//2个字节,位域不能跨字节存储
cout<<sizeof(aa)<<endl;
}
#include<iostream>
using namespace std;
struct aa
{
int d:1;
char a:2;
};
void main()
{
//位域不能跨类型存储
//字节对齐 8
cout<<sizeof(aa)<<endl;
}
#include<iostream>
using namespace std;
struct aa
{
int d:1;
char a:9;//位域不能超过其对应的位数
};
void main()
{
cout<<sizeof(aa)<<endl;
}
柔性数组
1、柔性数组不占内存,可以自动增长
2、柔性数组必须在结构体最后一个
3、柔性数组操作存储与栈区的字符串
#include<iostream>
using namespace std;
struct A
{
int a ;
double b;
char c[0];
};
void main()
{
char str[]="hello world !";
struct A st;
//16
cout<<st.c<<endl;
//hello world !
cout<<sizeof(A)<<endl;
}