C语言 --- 指针详解(上)

文章通过C语言代码示例,详细解释了指针和数组的关系,以及sizeof运算符用于计算内存占用和strlen函数用于计算字符串长度的区别。指针表示内存地址,数组名在不同上下文有不同的含义,sizeof计算的是内存大小,而strlen则寻找字符串结束符。
摘要由CSDN通过智能技术生成

通过例子来带领大家理解指针和数组的关系以及strlen函数和sizeof的区别

#include<stdio.h>
#include<string.h>
//数组名在绝大多数情况下代表首元素的地址
//但在两种情况下例外
//1.sizeof(数组名)中的数组名代表整个数组,即计算整个数组的大小
//2.&数组名中的数组名代表整个数组,即取出整个数组的地址(该地址的类型是数组指针)
//注意:地址的大小一定只与电脑硬件有关,不管是什么类型,32位机器是4字节,64位机器是8字节
int main()
{
	//一维数组
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16 —— 计算整个数组的大小
	printf("%d\n", sizeof(a + 0));// 4 / 8 
	//a不是单独放在sizeof里面,所以代表首元素的地址,加0还是首元素的地址,地址大小4/8字节
	printf("%d\n", sizeof(*a));//4 -- a不是单独放在sizeof里面,代表首元素的地址,*解引用取到第一个元素,大小是4
	printf("%d\n", sizeof(a + 1));//4 / 8,解析同a+0,a+1代表第二个元素的地址
	printf("%d\n", sizeof(a[1]));//4 -- 取第二个元素
	printf("%d\n", sizeof(&a));//4 / 8,&a取整个元素的地址,但地址的大小不变还是4/8
	printf("%d\n", sizeof(*&a));//16 -- *&两者相互抵消,就相当于是sizeof(a)
	//或者说&a是取整个数组的地址,*解引用之后得到整个数组,sizeof计算的是整个数组的大小
	printf("%d\n", sizeof(&a + 1));//4 / 8,&a+1跳过一整个数组的地址,还是地址,大小4/8
	printf("%d\n", sizeof(&a[0]));//4 / 8,取的首元素地址
	printf("%d\n", sizeof(&a[0] + 1));//4 / 8,取的第二个元素的地址


	//字符数组
	char arr[] = { 'a','b','c','d','e','f' };//注意没有\0,不是字符串
	printf("%d\n", sizeof(arr));//6 -- 计算整个数组的大小
	printf("%d\n", sizeof(arr + 0));//4 / 8,arr代表首元素的地址,+0还是首元素的地址
	printf("%d\n", sizeof(*arr));//1 -- arr代表首元素的地址,*解引用得到第一个元素,char类型大小是1
	printf("%d\n", sizeof(arr[1]));//1 --取的第二个元素大小是1
	printf("%d\n", sizeof(&arr));//4 / 8,&arr得到整个数组的地址,还是地址
	printf("%d\n", sizeof(&arr + 1));//4 / 8,&arr得到整个数组的地址,+1跳过整个数组,但还是地址
	printf("%d\n", sizeof(&arr[0] + 1));//4 / 8,取到第二个元素的地址

	//strlen计算字符串的大小(实际是在找\0的位置)
	printf("%d\n", strlen(arr));//随机值,arr[]不是字符串数组,\0的位置未知
	printf("%d\n", strlen(arr + 0));//随机值,同上
	printf("%d\n", strlen(*arr));//err,strlen接受的参数是地址,*arr代表第一个元素'a'--97(ASCII)
	//97被传过去当地址,strlen会非法访问这个地址,会报错
	printf("%d\n", strlen(arr[1]));//err,同上
	printf("%d\n", strlen(&arr));//随机值,&arr是整个数组的地址,传过去之后被当作首元素地址
	printf("%d\n", strlen(&arr + 1));//随机值-6,&arr+1是跳过数组的地址即'f'后面的地址,\0的位置依旧未知
	printf("%d\n", strlen(&arr[0] + 1));//随机值-1,取的第二个元素的地址

	char arr[] = "abcdef";//是字符串
	printf("%d\n", sizeof(arr));//7 -- 计算整个数组的大小,注意是字符串,别忘了还有\0
	printf("%d\n", sizeof(arr + 0));//4 / 8,首元素的地址
	printf("%d\n", sizeof(*arr));//1 -- 第一个元素
	printf("%d\n", sizeof(arr[1]));//1 -- 第二个元素
	printf("%d\n", sizeof(&arr));//4 / 8,取整个数组的地址,还是地址
	printf("%d\n", sizeof(&arr + 1));//4 / 8,&arr+1跳过整个数组的地址即'\0'后面的地址
	printf("%d\n", sizeof(&arr[0] + 1));//4 / 8,取的第二个元素的地址

	printf("%d\n", strlen(arr));//6 -- 计算字符串的大小
	printf("%d\n", strlen(arr + 0));//6 -- 传的首元素的地址,\0之前有6个元素
	printf("%d\n", strlen(*arr));//err,strlen接受的参数是地址,*arr代表第一个元素'a'--97(ASCII)
	//97被传过去当地址,strlen会非法访问这个地址,会报错
	printf("%d\n", strlen(arr[1]));//err,同上
	printf("%d\n", strlen(&arr));//6 -- &arr是整个元素的地址但值依旧是首元素的地址
	printf("%d\n", strlen(&arr + 1));//随机值 -- &arr+1跳过整个数组的地址即'\0'后面的地址,这个地址往后\0的位置未知
	printf("%d\n", strlen(&arr[0] + 1));//5 -- 传的第二个元素的地址

	char* p = "abcdef";//p记录的首元素地址
	printf("%d\n", sizeof(p));//4 / 8,p指针存放地址,还是地址的大小(指针和地址的大小相同)
	printf("%d\n", sizeof(p + 1));//4 / 8,p+1是第二个元素的地址,还是地址
	printf("%d\n", sizeof(*p));//1 -- *p取得第一个元素
	printf("%d\n", sizeof(p[0]));//1 -- 同上
	printf("%d\n", sizeof(&p));//4 / 8,&p得到指针p的地址,还是地址
	printf("%d\n", sizeof(&p + 1));//4 / 8,&p+1得到p之后的地址,还是地址
	printf("%d\n", sizeof(&p[0] + 1));//4 / 8,&p[0]得到第一个元素地址,+1得到第二个元素的地址

	printf("%d\n", strlen(p));//6 -- 计算的字符串长度
	printf("%d\n", strlen(p + 1));//5 -- 计算的从第二个元素开始的字符串长度
	printf("%d\n", strlen(*p));//err,*p代表第一个元素'a'--97(ASCII)
	//97被传过去当地址,strlen会非法访问这个地址,会报错
	printf("%d\n", strlen(p[0]));//err,同上
	printf("%d\n", strlen(&p));//随机值,&p得到指针p的地址,之后的\0位置未知
	printf("%d\n", strlen(&p + 1));//随机值,&p+1得到指针p地址的后一个地址,之后的\0位置未知(上下两个随机值没有任何关系)
	printf("%d\n", strlen(&p[0] + 1));//5 -- &p[0]得到第一个元素地址,+1得到第二个元素的地址,
	//即计算从第二个元素开始的字符串长度

	//二维数组
	int a[3][4] = { 0 };
	//可以看成是3个一维数组组成,故a[]可以看成是每个一维数组的数组名,代表首元素a[][0]的地址或这一行数组
	//而a则是二维数组的数组名,代表首元素a[0]地址或整个数组,注意这个a[0]是第一行的数组名,不是第一个元素,a是以这三个一维数组的数组名为元素
	//只是a、a[0]和&a[0][0]的值相同,但意义完全不同!!!
	printf("%d\n", sizeof(a));//48 -- 计算整个二位数组的大小
	printf("%d\n", sizeof(a[0][0]));//4 -- a[0][0]第一个元素的大小
	printf("%d\n", sizeof(a[0]));//16 -- a[0]数组名单独放在sizeof内,代表整个数组,即计算第一行的大小
	printf("%d\n", sizeof(a[0] + 1));//4 / 8 -- a[0]不是单独放在sizeof里面,代表首元素地址,而第一行的首元素就是a[0][0]
	//+1就是arr[0][1]的地址
	printf("%d\n", sizeof(*(a[0] + 1)));//4 -- 计算第二个元素的大小
	printf("%d\n", sizeof(a + 1));//4 / 8,a不是单独放在sizeof里面,代表首元素地址,即a[0],+1代表第二个元素a[1]的地址
	printf("%d\n", sizeof(*(a + 1)));//16 -- a不是单独放在sizeof里面,代表首元素地址,即a[0],+1代表第二个元素a[1]的地址
	//*解引用得到第二行数组,即计算第二行数组的大小
	printf("%d\n", sizeof(&a[0] + 1));//4 / 8,&a[0]--&数组名,得到第一行的数组地址,+1得到第二行的数组地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//16 -- &a[0]--&数组名,得到第一行的数组地址,+1得到第二行的数组地址,*得到第二行数组,即计算第二行数组的大小
	printf("%d\n", sizeof(*a));//16 -- a代表首元素a[0]的地址,*解引用得到第一行数组,即计算第一行数组的大小
	printf("%d\n", sizeof(a[3]));//16 -- a[3]是第四行的数组名,代表第四行数组,即计算第四行数组的大小
	//注意:不必担心第四行是否存在,sizeof是操作符,里面的表达式不进行计算,只通过类型判断大小,故不必担心越界的问题
	return 0;
}

友情提醒:该上诉代码有的会报错,如要验证,请自行去除错误的代码行(即后面标注err的)

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值