指针(一)

1.什么是指针(指针的定义)

要点:指针就是地址,地址就是指针,通过指针可以间接访问内存中存储的数据。

生活中,一栋宿舍楼每个房间都有门牌号,这样就可以很快地找到一个想要找的房间,计算机中的内存也是如此,我们把内存划分为一个个的内存单元,每个内存单元也都有一个编号,计算机中我们叫它为地址,C语言中也叫指针。所以我们认为内存单元=地址=指针

2.变量的指针和指向变量的指针变量

要点:变量的指针就是变量的地址,存放变量地址的变量叫指针变量。

2.1取地址操作符--&

2.2指针变量

C语言中,我们通过取地址操作符(&)取出地址存放到的地方叫做指针变量,指针变量也是变量,所以指针变量的定义与变量的语法格式基本相同,只是指针变量是专门用来存地址的。

指针变量一般形式

类型说明符* 变量名[=地址表达式]

例如

#include <stdio.h>
int main()
{
	int a = 1;
	int* p = &a;//取出a的地址并存放在指针变量a中
	return 0;
}

怎么理解指针的类型呢?我们看到p的类型是int*, p的左边是int*,*在说明p是指针变量,而*前面的int是在说明p指向的是整型对象。

2.3解引用操作符(*)

生活中,我们通过门牌号可以找到一个房间,可以在房间里拿想要拿的东西,C语言当中也是如此,我们通过地址(指针)可以找到地址指向对象,那以后想要使用地址指向的这个对象,就得使用解引用操作符来获取。

例如

#include <stdio.h>
int main()
{
	int a = 1;
	int* p = &a;
	*p = 0;
}

上述代码, *p的意思就是通过p中存放的地址,来找到地址所指向的对象,*p其实就是变量了,*p=0的意思就是给a赋值为0了。

3.指针的运算

3.1 指针+-整数

指针变量的值是可以进行运算的,但运算规律比较特殊,不是简单的加减法,而是运算对象数据类型相关的运算,直观上可以理解为数组元素访问位置的变化,也就是+代表指向元素后面,-代表指向元素前面。

例如

创建一个10个元素的整型数组,通过指针+-运算符就可以访问数组中各个元素了。

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//指针+-整数
	}
}

这里p+i就是指针+-整数,*(p+i)就是访问数组中的元素了。

3.2 指针-指针

我们在模拟实现strlen库函数的时候就运用到了指针-指针

//指针-指针
#include <stdio.h>
int my_strlen(char* s)
{
	char* p = s;
	while (*p != '\0')
		p++;
	return p - s;
}
int main()
{
	printf("%d", my_strlen("abc"));
	return 0;
}

3.3 指针的关系运算

指针也可以比较大小的,例如

//指针的关系运算
#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	while (p < arr + sz)//指针比较大小 
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

4.指针的使用和传址调用

4.1 指针的使用

我们可以通过指针来模拟实现strlen库函数,strlen函数的功能是统计一个字符串\0之前的字符个数。如果要模拟实现这个功能,就只需从起始地址遍历整个字符串,只要不是\0,计数器就加一,这样就模拟出该功能了,假设参数s接收字符串的起始地址,然后遍历\0之前的字符串,返回该长度即位字符串个数。

代码如下:

#include <stdio.h>
int my_strlen(char* s)
{
	int count = 0;
	while (*s)
	{
		s++;
		count++;
	}
	return count;
}
int main()
{
	int len = my_strlen("abcd");
	printf("%d ", len);
	return 0;
}

4.2  传值调用和传址调用

我们学习了指针,那指针是非用不可吗?答案是错,指针并非非用不可,我们可以使用指针对一些复杂的问题设计出更加优异且灵活的算法,更好地实现任务需求。

例如,写一个函数,实现两个整型变量的交换。

代码如下:

#include <stdio.h>
void Swap(int x, int y)
{
	int temp = 0;
	temp = x;
	x = y;
	y = temp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d,b=%d\n", a, b);
	Swap(a, b);
	printf("交换后:a=%d,b=%d\n", a, b);
}

结果如上,显然该代码并未实现两个整型变量的交换,那是为什么呢?我们通过调试可以发现:

主函数中,创建了变量a和b,a的地址是0x0000001cc033f8f4,b的地址是0x0000001cc033f914,通过Swap函数将主函数里的实参a和b传给了Swap函数里的形参x和y,但是从调试结果看到x和y都有相应的地址,分别是0x0000001cc033f8d0,0x0000001cc033f8d8,x和y确实接收到了a和b的值,但是x和y都有各自独立的空间,在Swap函数里对x和y进行替换,自然不会影响到a和b,Swap函数在使用的时候直接把变量传给了函数本身,这种叫做传值调用

要点:使用函数时,实参传递给形参,形参会单独会创建一个临时空间来接收实参,对形参的改变并不会影响实参。

那我们如果想实现该任务,我们该怎么做呢,这就得运用到指针了。 在主函数里,将a和b的地址传给Swap函数,Swap函数里通过地址间接地访问a和b,这样就可以实现两整型变量的替换了。

代码如下:

#include <stdio.h>
void Swap(int* x, int *y)
{
	int temp = 0;
	temp = *x;
	*x = *y;
	*y = temp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d,b=%d\n", a, b);
	Swap(&a, &b);
	printf("交换后:a=%d,b=%d\n", a, b);
}

通过结果我们可以看到该代码完成了任务,这里调用Swap函数是将变量的地址传给了函数,这种函数调用方式叫做传址调用。 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值