C语言学习 指针(1)

2023.08.11

指针是什么?怎么样形象的理解指针?这是我在学习的时候十分关注的点。

要想很好的理解指针,先要了解一下内存和地址的概念。

在计算机中,所有的数据都是存储在内存中的,要想处理数据的时候都是要从内存中先读取数据,再进行处理。为了高效的管理与利用内存,内存被划分为一个个的内存单元,每个内存单元的大小取一个字节。而每个内存单元也有一个自己的编号,有了这个内存单元的编号,CPU就可以快速的找到一个内存空间。而这个编号就叫做地址,在C语言中也叫作指针。通过这个地址即指针,就能够找到以它为地址的内存单元。

即内存单元的编号==地址==指针。

指针变量和地址

取地址操作符&

在C语言中,创建变量就是向内存申请空间,根据变量的类型分配给相对应的字节个数。

假如现在创建一个变量名为a的整型变量,要想知道这个变量a在内存中的存储地址,就需要使用到取地址操作符&。

int main()
{
	int a = 1;
	&a;
	printf("变量a的地址是%p", &a);
	return 0;
}

运行这个代码可知,我们找到了变量a的地址。整型变量a占4个字节,取出的是a所占4个字节中地址较小的那个地址,只要知道了最小的那个地址,就能够知道其他字节的地址。

指针变量和解引用操作符

定义指针变量

一般形式 :类型名 * 指针变量名

指针变量是一种变量,用来存放地址,只要是存放在指针变量中的值都会被理解成为一个地址。

int * point_1;

int 为基类型,用来指定此指针变量可以指向的变量的类型,即point_1这个指针变量只可以指向整型变量的地址。后面也学到,基类型也决定了指针在解引用时可以访问的字节个数,也决定了指针的步长,后面讲指针运算时再详细说。

* 表示该变量为指针型变量,定义时不能漏写。

int * 为该指针的类型,读作“指向int的指针”或者“int指针”。

point_1 为该指针变量的名字。

指针变量也可以在定义的时候进行初始化,int * point_1 = &a; 

注意,在这里,a的地址是赋给了 point_1 而不是 * point_1 ,* point_1是解引用指针变量,表示这个地址所对应的变量,即为a。

解引用操作符

定义指针变量后,要想通过指针变量找到指针指向的变量,就需要解引用指针变量,这里就需要用到解引用操作符 * 。* point_1 实际上就表示变量a了。

输入a和b两个整数,按先大后小的顺序输出a和b,注意使用函数处理,并且使用指针变量作为函数参数。

①交换的是指针变量所指向变量的值,即交换了a和b的值。

#include <assert.h>

void swap(int* p1, int* p2)//形参是指针变量,所以传过来的实参要是地址而不是数值,否则会引起读取访问权限冲突的错误
{
	assert(p1 != NULL && p2 != NULL);//这个断言用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行。
	if (*p1 < *p2)//比较a和b的大小,当a<b时进行操作
	{
		int temp;
		temp = *p1;
		*p1 = *p2;
		*p2 = temp;
		//交换a和b的值,使得a总为大数,b为小数
	}
}

int main()
{
	int a, b;
	int* p1 = &a;//将a的地址赋给p1
	int* p2 = &b;//将b的地址赋给p2
	printf("输入两个数a和b:");
	scanf("%d %d", &a, &b);
	swap(p1, p2);//进行比较大小的操作,函数调用,将a和b的地址传过去
	printf("a=%d,b=%d\n", a, b);
	printf("max=%d,min=%d", *p1,*p2);
	return 0;
}

②交换的是指针变量的值(地址)

void swap(int* p1, int* p2)//形参是指针变量,所以传过来的实参要是地址而不是数值,否则会引起读取访问权限冲突的错误
{
assert(p1 != NULL && p2 != NULL);//这个断言用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行。
if (*p1 < *p2)//比较a和b的大小,当a<b时进行操作
    {
		int temp;
		temp = p1;
		p1 = p2;
		p2 = temp;
		//交换a和b的地址,使得p1总为大数的地址,p2为小数的地址
    }
}

③将变量作为实参传递给调用函数做形参

void swap(int x, int y)
{
	int temp;
	temp = x;
	x = y;
	y = temp;
}
//这个代码为我初学时想使用的代码,但是发现。。。

只有①可以实现两数交换的目的,②③都不可以。

注意:要想通过调用函数的方法将变量交换,不能采取把要改变的变量作为参数的办法,(由于“单向传递”的“值传递”方式,不能企图通过改变形参的值来改变实参的值)。因此不管是将变量直接作为参数传递还是将指针变量作为参数传递,是不能通过改变形参指针变量的值(地址)来改变实参指针变量的值(地址)。应该使用指针变量作为函数参数,在函数执行过程中使指针变量所指向变量的值发生变化,(可以改变实参指针所指向变量的值),在函数调用结束之后这些变化依然能够被保存下来。

通过函数调用改变n个要改变的值:

①在主调函数中设置n个变量,用n个指针变量指向它们;

②在主调函数中将这n个指针变量作为实参传给调用函数,即将相关变量的地址传给调用函数。

③设置一个调用函数,有n个指针形参。在这个函数中改变这n个形参的值;

主调函数就可以使用这些已经改变的变量。

交换p1和p2:实际上是交换两指针变量的变量值(地址),改变指针变量解引用所指向的变量。但是对于解引用指向的变量,变量地址与变量值并未发生改变。

交换a和b:实际上是改变变量的值,对于指针变量的变量值(地址)没改变,指针变量解引用所指向的变量也没改变,改变的是解引用指向的变量的值。

输入三个整数a,b,c,要求按从大到小的顺序将他们输出。用函数实现。

void swap(int* pm, int* pn)
{
	int temp = *pm;
	*pm = *pn;
	*pn = temp;
    //可以改变实参指针变量所指变量的值
}

int exchange(int* p1, int* p2, int* p3)
{
	if (*p1 < *p2) swap(p1, p2);
	if (*p1 < *p3) swap(p1, p3);
	if (*p2 < *p3) swap(p2, p3);
}

int main()
{
	int a, b, c;
	int pointer_1 = &a;
	int pointer_2 = &b;
	int pointer_3 = &c;
	printf("输入三个数a,b,c:");
	scanf("%d %d %d", &a, &b, &c);
	exchange(pointer_1, pointer_2, pointer_3);
	printf("按由大到小的顺序输出:%d %d %d", a, b, c);
	return 0;
}

指针变量类型的意义

指针的类型决定了,在对指针解引用时的权限大小(一次能操作几个字节)。

char * 的指针解引用只能访问一个字节,int * 的指针解引用能访问4个字节。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值