c指针

举报
秋名山码民 发表于 2022/03/31 17:32:57 2022/03/31
【摘要】 关于作者:2019NOIP退役成员,学习c语言已有多年经验,更懂得考试的题目,和初学者学习时所遇到的问题华为云享专家,以及CSDN的新星创作者,有写博客的一定能力 关于本栏目本栏目的宗旨是带你入门c语言,作者打算用题海+c语言的概念来完成本栏目,适用人群:面向广大的编程爱好者和大学生来进行创作学完本栏后你能达到的水平:计算机二级水平左右,入门c语言学习题目:主要来源于网络和c语言的入门算法...

关于作者:

2019NOIP退役成员,学习c语言已有多年经验,更懂得考试的题目,和初学者学习时所遇到的问题

华为云享专家,以及CSDN的新星创作者,有写博客的一定能力

关于本栏目

本栏目的宗旨是带你入门c语言,作者打算用题海+c语言的概念来完成本栏目,

适用人群:面向广大的编程爱好者和大学生来进行创作

学完本栏后你能达到的水平:计算机二级水平左右,入门c语言学习

题目:主要来源于网络和c语言的入门算法题目

写在前面的话(第十一天)

记住我们的宗旨:努力去做,让一切交给时间来评判!

指针由于它和内存相对应,对初学者来说还是比较难理解的,本节需要大家仔细品味

指针

在c中提出专门的类型来表示变量的地址

char* 表示一个char型变量的地址
int* 表示一个int型变量的地址
flot* 表示一个float型变量的地址
double* 表示一个double型变量的地址
……

在这里插入图片描述

带*号变量的表示一个指针型变量,简称指针

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int *p = &a;//p指向a的地址
	printf("%d\n", *p);//*p为解引用操作,输出p所存储的值
	p = &b;//将p的地址修改为b的地址
	printf("%d", *p);
}

在这里插入图片描述
不同类型的指针不能相互赋值,像这样,char* p与int *q;
具体的来说,char * 称之为char型指针类型,int *称之为int型指针类型

在用printf打印时,通常可以使用%p来打印,p为pointer
*号的位置可以自由,

int *a
int* a
int * a

星号操作

*来返回位于操作数所指定地址的变量的值

#include<stdio.h>
int main()
{
	int a = 1;
	int *p = &a;
	*p = 123;//写操作:修改p地址中的值
	printf("%d\n", a);
	int b = *p;//读操作:读取p地址中的值赋值给b
	int c = *p + 1;
	printf("%d %d\n", b, c);
}

在这里插入图片描述
区别星号,在定义一个变量的时候,星号表示一个指针类型,
在星号操作中,星号表示读写内存的值。

指针变量的初始化

作为一个指针变量,有以下几种初始化的操作

  1. 利用取地址获取 x 的地址,在指针变量 p定义时,赋值给 p,
    像我们上文中的一样
  2. 定义指针变量,分别赋值“NULL”和“0”,称之为空指针

在c中值为0的指针,我们称之为空指针,当指针为空的时候,不能使用*号操作,那么如何判断呢?

if(p)//当指针p不为空时候
{
	printf("%p",p);
}

指针不同于其他变量的运算规则

指针变量的加减法,和普通整型变量的加减法是不同的,当指针加减是,是以元素为单位进行移动的,例如,p+1便是移动到后一个元素,p-1便是移动到前一个元素

//定义三个变量,假设它们地址为连续的,分别为 4000、4004、4008
int x, y, z;

//定义一个指针,指向 x
int *px = &x;

//利用指针变量 px 加减整数,分别输出 x、y、z
printf("x = %d", *px);		//因为 px 指向 x,所以*px = x

//px + 1,表示,向前移动一个单元(从 4000 到 4004)
//这里要先(px + 1),再*(px + 1)获取内容,因为单目运算符“*”优先级高于双目运算符“+”
printf("y = %d", *(px + 1));		
printf("z = %d", *(px + 2));

关系运算

作为变量,那么它也应该是可以比较的,我们来看

  1. px > py 表示 px 指向的存储地址是否大于 py 指向的地址
  2. px == py 表示 px 和 py 是否指向同一个存储单元
  3. p==0,表示空指针,这个比较常用

指针数组

在数组一讲中我们知道数组在内存中相当于一串紧密排列的变量,实际上,数组名表示的就是这一块内存的首地址

对于一个int型数组来说,其地址类型为int*,可以理解为数组名本身的类型为int,可以用一个指针类型变量来存储数组的首地址

#include<stdio.h>
int main()
{
	int arr[4];
	printf("%p\n", arr);
	int *p = arr;
	int *p1 = &arr[0];
	printf("%p %p", p, p1);
	return 0;
}

在这里插入图片描述
都是相同的地址,也印证了我们上文所述。

指针与数组的转换:

p指向arr的任意一个元素:

  1. p = arr+3; //指向arr[3]
  2. p = &arr[3];

给数组元素赋值:

  1. arr[3] =10;
  2. *(arr+3) = 10;
  3. int *p = arr+3;
    *p = 10;

数组的遍历:
数组的方法,我们就不再赘述了,下面我们用指针来看

#include<stdio.h>
int main()
{
	int arr[4] = { 0,1,2,3 };
	for (int *p = arr; p < arr + 4; p++)
	{
		printf("%d ", *p);
	}
	return 0;
}

在这里插入图片描述

指针和函数

指针可以作为函数的参数,在函数中,我们可以使用这个指针,来访问目标内存的值

#include<stdio.h>
void test01(int *p)
{
	*p = 0;
}
int main()
{
	int a = 1;
	test01(&a);//将a的地址传入test01中
	printf("%d", a);
	return 0;
}

在这里插入图片描述
我们将a传入test01中,在test01中又将a地址的值进行改变,最后在main中输出a,为0

下面我们来说在函数中,留下的问题,swap交换

void swap(int *a,int *b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

根据地址值的交换来完成了俩个值在函数中交换,从而才能实现main函数中的俩个数的交换

数组作为函数的参数

由于我们上面说数组名就是地址,所以只要把数组的地址和长度传递给函数,就可以把数组内容传递给函数

我们来设计一个函数求一个数组中元素的和

#include<stdio.h>
int sum(int *p, int len)
{
	int sum = 0;
	for (int i = 0; i < len; i++)
	{
		sum += p[i];
	}
	return sum;
}
int main()
{
	int arr[5] = { 0,1,2,3,4 };
	int s = sum(arr, 5);
	//数组的名字就是数组的地址
	printf("%d", s);
	return 0;
}

还有一种等价写法,

int sum(int p[],int len)

函数的返回值为指针

数据类型 *函数名(参数列表){
	函数体
}
//例如:
int s;
int *sum(int x, int y){
	s = x + y;
	return &s;
}

多级指针

作为初学者,我们可以只了解一下二级指针足以
在这里插入图片描述

//定义普通变量和指针变量
int *pi, i = 10;
//定义二级指针变量
int **ppi;

//给指针变量赋初值
pi = &i;

//给二级指针变量赋初值
ppi = &pi;

//我们可以直接用二级指针做普通指针的操作
//获取 i 的内容
printf("i = %d", **ppi);
//获取 i 的地址
printf("i 的地址为%d", *ppi);

在初始化二级指针 ppi 时,不能直接 ppi = &&i,因为&i 获取的是一个具体的数值,而具体数字是没有指针的。

const指针

在普通指针前面加const就得到一个新的类型称之为const指针,相应的变量称之为const指针变量

int a = 0;
const int *p = &a; 

const在前面讲变量那讲我们说过是常量的意思,一旦确定不能修改,下面我们来看指针中的const

不加const

int a = 10;
int *p = &a;
*p = 11;//内存写
int b = *p;//内存可读

加const

int a = 10;
const int *p = &a;
*p = 10;//内存不可以写
int b = *p;//内存可以读

简单的来说const就是封存住了指针星号操作里面的写内存功能

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。