本文主要记录了 sizeof 操作符 和 strlen() 函数的区别,以及各自的用途。(在下才疏学浅,发现错误,还请留言指正)
sizeof 和 strlen 的区别
示例代码如下:
#include<stdio.h> int main() { char str[20]="0123456789"; printf("strlen(str)==%d ",strlen(str));//计算字符串的长度(不包括0x00),结果:10 printf("sizeof(str)==%d ",sizeof(str));//大小不退化,结果:20 char* ss = "0123456789"; printf("strlen(ss)==%d ",strlen(ss));//结果:10 printf("sizeof(ss)==%d ",sizeof(ss));//计算ss指针占用内存空间的大小,结果:4 return 0; }
- 从代码着色我们就可以看出来,sizeof是操作符,strlen是函数。
- sizeof操作符的结果类型是size_t,它的头文件在typedef为unsigned int类型,无符号,可以存储最大对象字节的大小。
- sizeof可以用数据类型做参数,strlen只能使用char*做参数,且必须是以' '结尾的。
- 数组做sizeof不退化,但是,传递给strlen就退化为指针了。
- 大部分编译器在编译的时候sizeof就计算好了,这就是sizeof(x)可以用来定义数组维数的原因。strlen的结果要在运行的时候才能计算出来,他用来计算字符串的长度,不是类型占内存的大小。
- sizeof如果是类型的话,必须加括号,但是如果是变量名的话,可以不加括号,因为sizeof是个操作符,而不是函数。
sizeof有哪些作用?
- 与存储分配和i/o系统的例程进行通信。
void* malloc(size_t size);
size_t fread(void* ptr,size_t size,size_t nmemb,FILE* stream);
- 查看某个类型对象在内存中所占的单元字节。
void* memset(void* s,int c,sizeof(s));
- 在系统分配一对象时,让系统知道要分配多少个内存。
- 便于一些类型的扩充,在windows中很多结构类型就有一个专用的字段是用来存放该类型的字节的大小的。
- 由于操作符的字节数在实现时可能出现变化,建议在涉及操作数字节大小时用sizeof来代替常量计算。
- 如果,操作数是函数中的数值形参或函数类型的参数,则sizeof给出其指针的大小。
试着用sizeof 替换 strlen计算字符串的长度
像这种替换是很少用到的,之所以这样写,仅仅方便知识点的掌握。
//题意:计算字符串的长度,并转化大写。 #include <iostream> #include<string> using namespace std; void upperCase(char str[]) { int test = sizeof(str);//strlen(str) int test2 =sizeof(str[0]); for(size_t i=0;i<test/test2;++i)//i<test { if( 'a' <= str[i] && str[i] <= 'z' ) str[i] -= ('a' - 'A'); } } int main() { char str[] = "aBcDe"; //从上面我们知道sizeof(数组),是不退化的,返回的结果是整个数组的大小,而不是里面元素的个数。 //如果数组的初始化为 char str[9] = "aBcDe",那么结果就不正确了。 cout<<"The length of str is:"<<sizeof(str)/sizeof(str[0])<<endl;//strlen(str) upperCase(str); cout << str << endl; return 0; }
sizeof计算 union联合体的大小
示例代码1:
#include <iostream> using namespace std; union u { double a; int b; }; union u2 { char a[13]; int b; }; union u3 { char a[13]; char b; }; int main() { cout<<"sizeof(u) == "<<sizeof(u)<<endl;//结果:8 cout<<"sizeof(u2) == "<<sizeof(u2)<<endl;//结果:16(使用了字节对齐) cout<<"sizeof(u3) == "<<sizeof(u3)<<endl;//结果:13(使用了字节对齐) return 0; }
union的大小取决于成员中占用空间最大的那个成员(考虑字节的对齐),同时,考虑字节对齐的符合数据类型有:union,class,struct
CPU对齐的问题,编译器会尽量把数据放在它的对齐上以提高CPU的命中率。可以使用#pragma pack(x)来修改编译器的对齐方式。
C++固有类型的对齐取编译器对齐方式与自身大小中较小的一个。例如:编译器以2对齐,int类型大小是4,则int的对齐是2和4中最小的2.因为默认的对齐是8(long double),所以固有类型的对齐方式就是自身。如果是符合类型,则都小于8的话,取成员类型最大的对齐。
示例代码2:
#include <iostream> using namespace std; #pragma pack(2)//手动将对齐方式修改为2,所以int的对齐也为2了。所以结果10,如果去掉这一句,则为12 union u { char buf[9]; int a; }; int main() { cout<<"sizeof(u) == "<<sizeof(u)<<endl; return 0; }