sizeof与strlen的区别
在C语言里,sizeof是运算符,而strlen是函数,sizeof在编译器编译的时候已经把结果计算出来了,而strlen的结果是要在程序运行到这个函数时才会计算出来。
二者返回的均是形参的内容长度,不同的是sizeof()返回的长度包含转义符 \0 ,而strlen()返回的长度不包括转义符 \0 ,只返回 \0 前的内容长度。
先说结论
使用sizeof()计算不同类型变量的大小,参照下表。
64位ubuntu系统生成32位程序文件
在ubuntu环境中,输命令vi sizeof_strlen_m32.c
创建.c文件,编译时在gcc编译命令加-m32参数,可在64位环境下编译32位文件:gcc sizeof_strlen_m32.c -o sizeof_strlen_m32 -m32
该命令需要安装几个库:
sudo apt-get update
sudo apt-get purge libc6-dev
sudo apt-get install libc6-dev
sudo apt-get install libc6-dev-i386
定义几组char型指针和数组,从以下代码来分析sizeof()和strlen()
char *str0 = "zxcvb!";
char *str1 = "zxcvbn";
char str2[] = "zxcvbn";
char str3[8] = {'z', 'x', 'c'};
char str4[] = "zx\0cv";
char str5[] = "zx\0\0cv";
char str6[] = "zx\0\0\ccv";
char str7[] = "zx\0\0\c\cv";
char str8[] = "zx\0\0\d\\cv";
./sizeof_strlen_m32
的运行结果:
sizeof(str0)=4,sizeof(*str0)=1
sizeof(str1)=4,strlen(str1)=6
sizeof(str2)=7,strlen(str2)=6
sizeof(str3)=8,strlen(str3)=3
sizeof(str4)=6,strlen(str4)=2
sizeof(str5)=7,strlen(str5)=2
sizeof(str6)=8,strlen(str6)=2
sizeof(str7)=8,strlen(str7)=2
sizeof(str8)=9,strlen(str8)=2
先说str0与*str0
定义:
char *str0 = "zxcvb!";
char *str1 = "zxcvbn";
结果:
sizeof(str0)=4,sizeof(*str0)=1
sizeof(str1)=4,strlen(str1)=6
由于 str0
是char型指针,sizeof()得到的是*str0
指针的地址空间,在32位时指针类型是4字节,故sizeof(str0)=4
。
sizeof(*str0)=1
中有*
号,表示取指针变量*str0 = "zxcvb!"中的第一个数据,即z
,char类型8位,所以得到的结果是1字节。
假若定义的是int *str0 = "zxcvb!";
,则sizeof(str0)=4
,当然了编译会有警告,字符只需8位的char类型,用了32位的int类型,警告可忽略。
*str1与str2[ ]、str3[8]
定义:
char *str1 = "zxcvbn";
char str2[] = "zxcvbn";
结果:
sizeof(str1)=4,strlen(str1)=6
sizeof(str2)=7,strlen(str2)=6
一个定义的是指针,一个是数组,内容一样都是zxcvbn
在内存中,str1与str2是这么存的,在字符串末尾有转义符 \0
,表示在这里结束。
sizeof(str1)=4
上面已经说过,32位的指针类型是4字节;
strlen(str1)=6
获取的是从该指针起始位置开始,一直到\0结束,strlen()计算长度不包含 \0
,故zxcvbn刚好6个字节。
如图中所示,\0占一个字节,sizeof()计算长度时会计入 \0
,所以zxcvbn
有6个字节+ \0
的1个字节,sizeof(str2)=7。
定义好数组长度的str3[8]
定义:
char str3[8] = {'z', 'x', 'c'};
结果:
sizeof(str3)=8,strlen(str3)=3
str3[8]定义了一个8 char长度的数组,前3位填入字符zxc,后5位为空。
从图中数组存储的位图可以看出,只有当数组在定义时没有指定数组长度时才有\0
结束符,如str2;当定义时已经指定数组长度,则没有\0
,如str3。
不管数组内是否为空,只要定义好数组长度,sizeof()返回的是该数组长度,sizeof(str3)=8
;strlen()返回的是数组中不为空的数据大小,strlen(str3)=3
。
从str4[ ]-str8[ ]看出 \0 与 \ 是怎么回事
定义:
char str4[] = "zx\0cv";
char str5[] = "zx\0\0cv";
char str6[] = "zx\0\0\ccv";
char str7[] = "zx\0\0\c\cv";
char str8[] = "zx\0\0\d\\cv";
结果:
sizeof(str4)=6,strlen(str4)=2
sizeof(str5)=7,strlen(str5)=2
sizeof(str6)=8,strlen(str6)=2
sizeof(str7)=8,strlen(str7)=2
sizeof(str8)=9,strlen(str8)=2
上面说\0
占存储位图中的1个字节,那么\与其他字符,\\在位图中是怎么存储的。
可以看出str5比str4多一个\0,从运行结果sizeof(str4)=6,sizeof(str5)=7可得出结论,\0组成的两个字符确实占1个字节。
数组str4[ ]、str5[ ]中的数据有"zx\0cv"
5个字节和"zx\0\0cv"
6个字节的长度,strlen(str4)
与strlen(str5)
的结果均为2。所以,并不是只有当\0
在数组末尾时才有结束作用,只要strlen()遇到\0
结束符就不会再计算后面的数据。
而从str6[ ]到str8[ ],从结果 sizeof(str6)=8,sizeof(str7)=8,sizeof(str8)=9
可看出,不论是\0
还是\d
、\\
,只要有转义符\
出现,该转义符及后一位数据均会被存储在同一个位图的格子中,占1个字符。
64位时的sizeof()和strlen()
同上面的过程类似,直接运行程序得出结论。
同32位时定义一样:
char *str0 = "zxcvb!";
char *str1 = "zxcvbn";
char str2[] = "zxcvbn";
char str3[8] = {'z', 'x', 'c'};
char str4[] = "zx\0cv";
char str5[] = "zx\0\0cv";
char str6[] = "zx\0\0\ccv";
char str7[] = "zx\0\0\c\cv";
char str8[] = "zx\0\0\d\\cv";
运行结果:
sizeof(str0)=8,sizeof(*str0)=1
sizeof(str1)=8,strlen(str1)=6
sizeof(str2)=7,strlen(str2)=6
sizeof(str3)=8,strlen(str3)=3
sizeof(str4)=6,strlen(str4)=2
sizeof(str5)=7,strlen(str5)=2
sizeof(str6)=8,strlen(str6)=2
sizeof(str7)=8,strlen(str7)=2
sizeof(str8)=9,strlen(str8)=2
由结果可以得出文章开头表格的结论。