【C语言-指针】

本文详细介绍了C语言中的指针,包括指针的概念,如内存地址和指针的大小;指针的类型,如字符指针、函数指针等;以及指针的运算,如比较、加减和解引用。此外,还探讨了指针与数组的关系,包括指针数组和数组指针,并通过示例解释了指针在内存中的表示和使用规则。
摘要由CSDN通过智能技术生成


前言

   指针的一些总结


一、指针

1.指针的概念

   指针是内存中最小单元的编号,也就是地址。一个最小的内存单元通常是一个字节。
   对于32位的机器,有32跟地址线,通电之后产生高电平(1)和低电平(0),就产生了32位0/1组成的二进制序列,就需要使用4个字节的空间来存储,会产生2的32次方个地址,同理64位的机器就需要使用8个字节的空间来存储,会产生2的64次方个地址,所以指针的大小是4/8个字节,每一个地址可以唯一的标识一个内存单元。

2.指针类型

char ch = ‘w’;
char* p = &ch;

   这里的p是一个字符指针,*代表p是一个指针,char表示p所指向的ch的类型是char。同理,还有其他类型的指针。

int * pi =NULL;
short* ps = NULL;
float* pf = NULL;
double* pd = NULL;
指针的定义方式:类型+*

   指针的类型决定了指针的步长(向前或向后走一步跳过几个字节)
   指针的类型决定了指针解引用能返回几个字节

#include <stdio.h>

int main()
{
	int a[] = { 0,1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(a) / sizeof(a[0]);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(a + i));
	}
	/*for (int i = 0; i < sz; i++)
	{
		printf("%d ", a[i]);
	}*/
	return 0;
}

   同时上面的例子也说明:在一块连续的内存空间中,*(数组名+i)等价于 数组名[i]

3.指针运算

   指针和指针之间可以进行比较,同时指针可以加减整数来访问前后的数据(不非法访问的情况下),同时指针减指针所求的是指针之间的元素个数,利用这一点,可以求字符串的长度

int my_strlen(const char* str)
{
	char* tail = str;
	while (*tail++)
		;
	return tail - str - 1;

}

4.字符指针

   字符指针有两种:

char s1[]=“hello world”;
char* ps = “hello world”;


   第一种的字符指针,本质上实在栈区上开辟的空间
   第二种的字符指针ps本质是将“hello world”首字符的地址放到了ps中,“hello world”是放在静态区上的的,所以*ps不能改变原字符串

在这里插入图片描述
   所以在初始化时,可以加上cosnt 让程序更加健壮
在这里插入图片描述

5.指针数组

   指针数组是指针的数组

int* arr1[10] 整形指针的数组
char* arr2[10] 字符指针的数组

   首先 ,arr1和[]结合,说明arr1是一个数组,数组有10个元素,每个元素类型是int*

6.指针数组

   指针数组是指针的数组

int(*p)[10]

   p首先和*结合,说明p是一个指针,指向的是一个数组,数组有10个元素,每个元素类型为int

   这里在说一下数组名和指针

数组名是数组首元素的地址,但有两个例外
1.sizeof(数组名),数组名单独出现在括号中,计算的是整个数组的大小,单位是字节
2.&数组名,取出的是整个数组的地址,加1跳过一个数组的大小

7.指针和数组习题

#include <stdio.h>
int main()
{
	一维数组
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//4*4 16
	//数组名单独放在括号里,计算的是整个数组的大小,单位是字节
	printf("%d\n", sizeof(a + 0));//4/8
	//这里的a既没有单独放在括号里,有没有&,所以a是数组首元素的地址,a+0还是首元素的地址,是地址就是4/8字节
	printf("%d\n", sizeof(*a));//4
	//a是首元素的地址,解引用就是数组的第一个元素,即sizeof(int)
	printf("%d\n", sizeof(a + 1));//4/8
	//a是首元素的地址,a+1是数组第二个元素的地址
	printf("%d\n", sizeof(a[1]));//4
	//a[1]即*(a+1),就是数组的第二个元素,即sizeof(int)
	printf("%d\n", sizeof(&a));//4/8
	//&a取出的是数组的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(*&a));//16
	//*和&操作相反,可以消去,所以还是sizeof(a)
	printf("%d\n", sizeof(&a + 1));//4/8
	//&a取出的是数组的地址,+1还是地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&a[0]));//4/8
	//取出的是数组首元素的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//取出的是数组首元素的地址,+1指向数组的第二个元素的地址,是地址就是4/8个字节
}
#include <stdio.h>
#include <string.h>
int main()
{
	//字符数组
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6
	//arr单独放在()里,计算的是整个数组的大小,单位是字节
	printf("%d\n", sizeof(arr + 0));//4/8
	//arr是首元素的地址,+0还是首元素的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(*arr));//1
	//arr是首元素的地址,解引用访问第一个元素,即sizeof(char)
	printf("%d\n", sizeof(arr[1]));//1
	//arr[1]=*(arr+1),arr是首元素的地址,加一之后解引用访问数组第二个元素,即sizeof(char)
	printf("%d\n", sizeof(&arr));//4/8
	//&arr,取出的是整个数组的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8
	//&arr,取出的是整个数组的地址,+1之后还是地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//4/8
	//&arr[0]取出的是数组首元素的地址,加一指向数组第二个元素的地址,是地址就是4/8个字节


	//strlen求字符串长度,直到遇到‘\0’才停止
	printf("%d\n", strlen(arr));//随机值
	//arr是首元素的地址,随机值,不知道‘\0’会出现在哪里
	printf("%d\n", strlen(arr + 0));//随机值
	//arr是首元素的地址,+0还是首元素的地址,随机值,不知道‘\0’会出现在哪里
	//printf("%d\n", strlen(*arr));error
	//*arr是数组的第一个元素,即‘a’,strlen的参数要求的是指针,会产生非法访问的内存错误;
	//printf("%d\n", strlen(arr[1]));//error
	//arr[1]=*(arr+1),*(arr+1)是数组的第二个元素,即‘b’,strlen的参数要求的是指针,会产生非法访问的内存错误;
	printf("%d\n", strlen(&arr));//随机值
	//&arr取出的是数组的地址,随机值,不知道‘\0’会出现在哪里
	printf("%d\n", strlen(&arr + 1));//随机值
	//&arr取出的是数组的地址,加一跳过一个数组,随机值,不知道‘\0’会出现在哪里
	printf("%d\n", strlen(&arr[0] + 1));//随机值
	//&arr[0]取出的是数组首元素的地址,加1指向数组的第二个元素,随机值,不知道‘\0’会出现在哪里
}
#include <stdio.h>
#include <string.h>

int main()
{

	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7,‘\0’也算一个字节
	//arr单独放在()里,计算的是整个数组的大小,单位是字节
	printf("%d\n", sizeof(arr + 0));//4/8
	//arr是数组首元素的地址,+0还是首元素的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(*arr));//1
	//*arr是数组首元素,即sizeof(char)
	printf("%d\n", sizeof(arr[1]));//1
	//arr[1] = *(arr+1),对数组的第二个元素解引用,就sizeof(char)
	printf("%d\n", sizeof(&arr));//4/8
	//&arr,取出的是整个数组的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8
	//&arr,取出的是整个数组的地址,+1还是地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//4/8
	//&a[0],取出的是数组首元素的地址,加1指向数组的第二个元素的地址,是地址就是4/8个字节


	printf("%d\n", strlen(arr));//6
	//arr是数组首元素的地址
	printf("%d\n", strlen(arr + 0));//6
	//arr是数组首元素的地址,+0还是数组首元素的地址
	//printf("%d\n", strlen(*arr));//error
	//*arr是对数组的首元素解引用,即‘a’,会产生非法访问内存的错误
	//printf("%d\n", strlen(arr[1]));//error
	//arr[1] = *(arr+1),*(arr+1)是对数组的第二个元素解引用,即‘b’,会产生非法访问内存的错误
	printf("%d\n", strlen(&arr));//6
	//&arr,取出的是整个数组的地址
	printf("%d\n", strlen(&arr + 1));//随机值
	//&arr,取出的是整个数组的地址,+1跳过整个数组,不知道后面‘\0’的位置,随机值
	printf("%d\n", strlen(&arr[0] + 1));//5
	//&arr[0]取出的是数组首元素的地址,+1指向数组的第二个元素
}
#include <stdio.h>
#include <string.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//4/8
	//p是指向'a'的指针,是指针就是4/8个字节
	printf("%d\n", sizeof(p + 1));//4/8
	//p是指向'a'的指针,+1指向‘b’,是指针就是4/8个字节
	printf("%d\n", sizeof(*p));//1
	//*p即sizeof(char)
	printf("%d\n", sizeof(p[0]));//1
	//p[0] = *(p+0),即sizeof(char)
	printf("%d\n", sizeof(&p));//4/8
	//&p是一个二级指针,是指针就是4/8个字节
	printf("%d\n", sizeof(&p + 1));//4/8
	//&p是一个二级指针,+1跳过一个一级指针的大小,是指针就是4/8个字节
	printf("%d\n", sizeof(&p[0] + 1));//4/8
	//&p[0],取出的是‘a’的地址,加一就是‘b’的地址

	printf("%d\n", strlen(p));//6
	//p指向字符串首元素
	printf("%d\n", strlen(p + 1));//5
	//p指向字符串首元素,+1即指向字符串第二个元素
	//printf("%d\n", strlen(*p));//error
	//*p首元素解引用,即‘a’,会产生非法访问内存的错误
	//printf("%d\n", strlen(p[0]));//error
	//p[0] = *p, 首元素解引用,即‘a’,会产生非法访问内存的错误
	printf("%d\n", strlen(&p));//随机值
	//&p取出的是p的地址,不知道后面‘\0’的位置,随机值
	printf("%d\n", strlen(&p + 1));//随机值
	//&p取出的是p的地址,+1跳过一个字符指针的大小,不知道后面‘\0’的位置,随机值
	printf("%d\n", strlen(&p[0] + 1));5
	//&p[0],指向字符串首元素,+1即指向字符串第二个元素
	return 0;
}
#include <stdio.h>
int main()
{
	//二维数组
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48
	//a单独放在()里,计算的是整个数组的大小,单位是字节
	printf("%d\n", sizeof(a[0][0]));//4
	//a[0][0]是数组第一行第一个元素
	printf("%d\n", sizeof(a[0]));//16
	//a[0]是数组第一行的函数名,函数名单独放在()里,计算的是整个数组的大小
	printf("%d\n", sizeof(a[0] + 1));//4/8
	//a[0]是数组第一行的函数名,即a[0][0]的地址,加一指向a[0][1],是地址就是4/8个字节
	printf("%d\n", sizeof(*(a[0] + 1)));//4
	//*(a[0] + 1)) = a[0][1],即数组第一行第二个元素
	printf("%d\n", sizeof(a + 1));//4/8
	//a表示首元素的地址,加一指向a[1],是地址就是4/8个字节
	printf("%d\n", sizeof(*(a + 1)));//16
	//*(a + 1) = a[1],就第二行的函数名,函数名单独放在()里,计算的是整个数组的大小
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//&a[0],取出的是数组首元素的地址,加一指向a[1],是地址,就是4/8个字节
	printf("%d\n", sizeof(*(&a[0] + 1)));//16
	//&a[0],可以看作a,即为a[1],就第二行的函数名,函数名单独放在()里,计算的是整个数组的大小
	printf("%d\n", sizeof(*a));//16
	//a是数组首元素的地址,*a 即a[0],数组第一行的函数名,函数名单独放在()里,计算的是整个数组的大小
	printf("%d\n", sizeof(a[3]));//16
	//a是数组首元素的地址,*a 即a[0],数组第四行的函数名,函数名单独放在()里,计算的是整个数组的大小
	//虽然没有第四行,但sizeof计算的是类型
	return 0;
}

8.函数指针

在这里插入图片描述
   在我们调用函数时,其实本质上都是在去call这个函数的地址。使用函数指针可以保存函数的地址。

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LRBORRR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值