c语言指针详解 第38课

上一节,我们了解了sizeof计算符和strlen函数的定义,接下来我们加强对它们的理解

首先,写一串代码,分析程序执行的结果,并分析原因

int main()
{
	char arr[] = "abcdef";
		printf("%d\n", sizeof(arr));          1 
		printf("%d\n", sizeof(arr+0));        2
		printf("%d\n", sizeof(*arr));         3
		printf("%d\n", sizeof(arr[1]));       4
		printf("%d\n", sizeof(&arr));         5
		printf("%d\n", sizeof(&arr+1));       6
		printf("%d\n", sizeof(&arr[0]+1));    7
		return 0;
}

一:7 首先,sizeof(arr)中的arr表示整个数组,数组内部的元素是字符串,所以内部的元素实际上是"abcdef/0"; 6个字母加上一个/0 ,一共七个元素,因为元素类型是char类型,所以一个元素所占的字节数为1,7个元素所占的字节数就为7.

二:4(32位平台) sizeof(arr+0)不表示整个数组,只有严格格式的sizeof(arr)中的arr才表示整个数组,所以这里的arr表示数组首元素的地址,既然是指针,一个指针所占的字节数为4(32位平台)

三:1 arr表示数组首元素的地址,*arr表示数组首元素,数组首元素为a,类型是char型,所以a所占的字节数为1

四:1 arr[1]表示数组第二个元素,第二个元素为b,类型为char型,所以所占的字节数也为1

五:4 &+数组名表示数组的地址,这里将数组的地址传递过去,既然是指针,所占的字节数就为4

六:4 &arr表示数组的地址,数组的地址+1表示跳过整个数组 但还是地址,所以占的字节数为4

七:4 &arr[0]表示数组首元素的地址,首元素地址+1表示数字第二个元素的地址,是地址,所以占的字节数就为4

所以打印的结果应该是 7 4 1 1 4 4 4 

 结果正确

同样的数组,我们使用strlen函数验证一下

int main()
{
	char arr[] = "abcdef";
		printf("%d\n", strlen(arr));       1
		printf("%d\n", strlen(arr+0));     2
		printf("%d\n", strlen(*arr));      3
		printf("%d\n", strlen(arr[1]));    4
		printf("%d\n", strlen(&arr));      5
		printf("%d\n", strlen(&arr+1));    6
		printf("%d\n", strlen(&arr[0]+1)); 7
		return 0;
	
}

代码如图所示

我们继续分析

一:6 strlen在计算时,是不计入/0的,/0只是strlen函数结束的标志,我们把数组首元素的地址传递过去,strlen函数运行,直到发现/0 一共六个元素,abcdef,每个元素所占的字节数都为1,所以结果为6

二:6 分析的过程和结果都和1相同

三:报错 arr表示数组首元素的地址,*表示对它进行解引用,*arr是数组首元素,数组首元素为a,strlen函数一般识别的是地址,a对应的ascii码是97,97对应的地址不在我们使用的范围内,形成越界访问,所以报错,结果如图所示

 四:报错 arr[2]表示数组第二个元素,数组第二个元素为b,b对应的ascii码值为98 ,98对应的地址不在我们的使用范围内,所以会形成越界访问,和三的结果相同

五:6 但会发生警告 ,因为&arr表示数组的地址,用代码表示就是char(*)[7],strlen函数的参数是(const char*),两个的类型不相同,不兼容,但依然能够强行赋值

六:随机值 &arr表示数组的地址,+1表示跳过数组的地址,也就是跳过了/0,下一个/0的位置是未知的,所以是随机值,也会产生和五相同的警告,警告的原因也是相同的,因为strlen函数的参数与我们的数组指针不兼容

七:5 &arr[0]表示数组首元素的地址,+1表示数组第二个元素的地址,也就是从b开始,到/0结束,一共是五个char类型的元素,所以是五个字节

int main()
{
	char*p = "abcdef";
	printf("%d\n", sizeof(p));             1
	printf("%d\n", sizeof(p+1));           2
	printf("%d\n", sizeof(*p));            3
	printf("%d\n", sizeof(p[0]));          4
	printf("%d\n", sizeof(&p));            5
	printf("%d\n", sizeof(&p+1));          6
	printf("%d\n", sizeof(&p[0]+1));       7
	return 0;
}

首先,要对char*p = "abcdef";进行解释

答: "abcdef"(char型)一共占用六个字节,但是正常的指针只占用4个字节,所以不能按照正常的解释:这里的"abcdef";是常量字符串:可以被访问,不允许通过解引用操作更改 这里的p是对应的是首元素的地址,即a的地址。

一:4 p这里表示首元素的地址,即a的地址,一个指针占四个字节,

二:4 p+1的得到的是数组第二个元素的地址,一个指针占四个字节

三:1 这里我们可以这样解释 :数组的第二个元素正常情况下应该怎样表示,有两种表示方法,1:arr[1] 2:*(arr+1)   类比可得*p=*(p+0)=arr[1] 所以这里表示数组首元素,数组首元素为a,所占的字节数为1

四:1 这里也可以类比  arr[0]表示数组首元素  所以p[0]也表示数组首元素,所占的字节数为1

五:4 &p可以类比&arr,所以这里表示数组的地址,无论是什么地址,所占的字节数都是固定的

六:4 &p表示数组的地址,&p+1表示跳过p数组的地址,因为是地址,所占的字节数不变。

七:4 &p[0]等价于&arr[0]表示数组首元素的地址,首元素的地址+1表示数组第二个元素的地址,因为是地址,所以所占的字节数为4

总结:遇到这种常量字符串对应的指针(p),可以用他们类比于arr计算

int main()
{
	char*p = "abcdef";
	printf("%d\n", strlen(p));                 1
	printf("%d\n", strlen(p+1));               2
	printf("%d\n", strlen(*p));                3
	printf("%d\n", strlen(p[0]));              4
	printf("%d\n", strlen(&p));                5
	printf("%d\n", strlen(&p+1));              6
	printf("%d\n", strlen(&p[0]+1));           7
	return 0;
}

对结果进行分析

这里的p是数组首元素的地址

一:6 p在这里的意思是首元素的地址 从a到/0一共6个元素,占6个字节

二:5 p+1表示第二个元素的地址

三:err 在这里表示首元素 因为strlen只能接收地址,所以发生错误

四:err 在这里也表示数组首元素

五:随机值 p是首元素的地址,&p表示到地址内部,例如p的地址是0x000016 ,,如果是小端存储,就是16 00 00 0x 第二个就是/0  /0所以根据地址的不同而发生变化 所以是随机值

六:随机值

七:4 &p[0]表示数组首元素的地址 +1表示数组第二个元素的地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值