C语言——深入理解指针(四)

发布于:2025-08-16 ⋅ 阅读:(25) ⋅ 点赞:(0)

C语言——深入理解指针(四)

数组名的意义

  • sizeof(数组名),且数组名单独放在sizeof内部,则这里的数组名表示整个数组,计算的是整个数组的大小
  • &数组名,这里的数组名表示的是整个数组,取出的是整个数组的地址
  • 除此之外所有的数组名都表示首元素的地址

sizeof和strlen的比较

1.sizeof是操作符,用于计算变量所占内存大小(不关注内存中存放什么数据),单位是字节
在这里插入图片描述
2.strlen是库函数(需要包含头文件<string.h>),求字符串长度。其统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。函数原型:

size_t strlen (const char* str)//返回类型注意为size_t

在这里插入图片描述
但若没有\0,就可能会存在越界查找,结果就是一个随机数,如下图所示:
在这里插入图片描述
3.比较
在这里插入图片描述

实例:

(一)一维数组

这里千万要注意前面提到的数组名的意义

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
printf("%zu\n", sizeof(a));//16
//a单独在sizeof里面代表整个数组,即四个元素乘以它们的类型所占字节
printf("%zu\n", sizeof(a+0));//4/8
//a没有单独在里面,所以代表首元素的地址,那么a+0还是首元素的地址,这里计算的是一个地址的大小不同环境有差别
printf("%zu\n", sizeof(*a));//4
//这里a没有单独放在sizeof内,a就是首元素地址,*a就是首元素1
printf("%zu\n", sizeof(a+1));//4/8
//a是首元素的地址,a+1就是第二个元素的地址
printf("%zu\n", sizeof(a[1]));//4
//第二个元素
printf("%zu\n", sizeof(&a));//4/8
//&a取出的是数组的地址,数组的地址也是地址
printf("%zu\n", sizeof(*&a));//16
//&a取出的是数组的地址,它的类型为int(*)[4]
//对于数组指针解引用,访问的则是这个数组
printf("%zu\n", sizeof(&a+1));//4/8
//&a是数组的地址,&a+1是跳过数组后的地址
printf("%zu\n", sizeof(&a[0]));//4/8
//第一个元素的地址
printf("%zu\n", sizeof(&a[0]+1));//4/8
//跳过第一个元素的地址,到达第二个元素的地址
return 0;
}

运行结果:
在这里插入图片描述

(二)字符数组

(1)操作符sizeof

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f'};
	printf("%zu\n", sizeof(arr));//6,计算整个数组
	printf("%zu\n", sizeof(arr + 0));//4/8,首元素的地址
	printf("%zu\n", sizeof(*arr));//1,*arr就是首元素
	printf("%zu\n", sizeof(arr[1]));//1,第二个元素
	printf("%zu\n", sizeof(&arr));//4/8,数组的地址
	printf("%zu\n", sizeof(&arr + 1));//4/8,依旧是地址
	printf("%zu\n", sizeof(&arr[0] + 1));//4/8,第二个元素的地址
	return 0;
}

运行结果:
在这里插入图片描述

#include<stdio.h>
int main()
{
	char* p = "abcdef";
	printf("%zu\n", sizeof(p));//4/8
	//p是一个指针变量,我们假设地址0x0012ff30
	printf("%zu\n", sizeof(p + 0));//4/8
	//p+1就是b的地址
	printf("%zu\n", sizeof(*p));//1
	//char*类型指针解引用只能访问一个字符
	printf("%zu\n", sizeof(p[0]));//1
	//p[0]->*(p+0)->*p,就是第一个元素
	printf("%zu\n", sizeof(&p));//4/8
	//&p是指针变量p的地址,是二级指针
	printf("%zu\n", sizeof(&p+ 1));//4/8
	printf("%zu\n", sizeof(&p[0] + 1));//4/8
	//&p[0]+1就是b的地址
	return 0;
}

在这里插入图片描述
在这里插入图片描述
(2)库函数strlen():

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zu\n", strlen(arr));//随机值
	//arr是数组首元素地址,strlen算的是整个数组,由于字符串中找不到\0,所以为随机值
	printf("%zu\n", strlen(arr + 0));//随机值
	//(arr+0)也是首元素地址
	printf("%zu\n", strlen(*arr));//程序崩溃
	//arr是首元素地址,*arr就是首元素即‘a’——97
	//这里就会出现非法访问内存
	printf("%zu\n", strlen(arr[1]));//程序崩溃
	//同上
	printf("%zu\n", strlen(&arr));//随机值
	//整个数组的地址,从数组的起始位置数字符串的长度,但是没有\0
	printf("%zu\n", strlen(&arr + 1));//随机值
	//跳过这个数组的地址,向后找\0
	printf("%zu\n", strlen(&arr[0] + 1));//随机值
	//从第二个元素的地址,向后找\0
	return 0;
}
int main()
{
	char* p = "abcdef";
	printf("%zu\n", strlen(p));//6
	//p就是a的地址,直至遇到\0向后数有6个字符
	printf("%zu\n", strlen(p+1));//5
	//p+1指向b,向后数直到遇到\0有五个字符
	printf("%zu\n", strlen(*p));//error
	//*p就是第一个字符
	printf("%zu\n", strlen(p[0]));//error
	//同上
	printf("%zu\n", strlen(&p));//随机值
	//p变量在内存中后续的空间内容不确定
	printf("%zu\n", strlen(&p+1));//随机值
	//同上
	printf("%zu\n", strlen(&p[0]+1));//5
	//&p[0]就是a的地址,&p[0]+1就是b的地址,从b的位置向后数
	return 0;
}

(三)二维数组

  • 这里还是要特别注意:数组名单独放在sizeof内,表示整个数组
  • 还要注意的一个点:sizeof在计算变量,数组的大小时,是通过类型来推导的,不会真实去访问内存,举个栗子:

在下图中,括号内s=a+2,其中a和2都是int类型,算出来s=12,但sizeof并不会去计算,而是看s本身是什么类型,short类型占两个字节,所以打印出来的仍是2而不是4;而打印s的值时,也不会因为在sizeof里面的算式而改变。

在这里插入图片描述

  • 实例
#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%zu\n", sizeof(a));//48
	printf("%zu\n", sizeof(a[0][0]));//4
	printf("%zu\n", sizeof(a[0]));//16
	//a[0]是第一行一维数组名,单独放在sizeof内部
	// 表示第一行这个数组
	printf("%zu\n", sizeof(a[0]+1));//4/8
	//a[0]没有单独放在sizeof中
	// 则a[0]是第一行第一个元素的地址,a[0]+1是第一行第二个元素的地址
	printf("%zu\n", sizeof(*(a[0] + 1)));//4
	//*(a[0] + 1)是第一行第二个元素
	printf("%zu\n", sizeof(a+1));//4/8
	//a未单独放在sizeof中,表示数组首元素的地址,就是第一行的地址
	// a+1就是第二行的地址
	printf("%zu\n", sizeof(*(a+1)));//16
	//a+1是第二行的地址,解引用就是a[1]这行数组,计算的是整个数组的大小
	printf("%zu\n", sizeof(&a[0]+1));//4/8
	//表示第二行的地址
	printf("%zu\n", sizeof(*( & a[0] + 1)));//16
	//第二行的地址解引用就是这一行
	printf("%zu\n", sizeof(*a));//16
	//a没有单独放在里面,是第一行的地址,解引用就是a[0]
	printf("%zu\n", sizeof(a[3]));//16
	//sizeof在计算变量,数组的大小时,是通过类型来推导的,不会真实去访问内存
	//所以这里不会有越界访问
	return 0;
}

在这里插入图片描述
我们来测试一下运行结果:
在这里插入图片描述

本次内容到这里就结束了,谢谢观看,如有不对欢迎在评论区留言指正。
心向往之行必能至!


网站公告

今日签到

点亮在社区的每一天
去签到