32位&64位环境中,sizeof和strlen求指针字符串、数组长度

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

由结果可以得出文章开头表格的结论。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值