深入理解指针---1

(一)什么是指针

指针就是存放变量内存地址的变量 怎么理解呢

我们电脑的内存分为8GB,16GB,32GB等等,而内存也被划分成一个个的内存单元,每个内存单元的大小取一个字节,每个内存单元就相当于一个学生宿舍,一个字节空间里又能放8个比特位,就像我们宿舍是8人间,每个人是一个比特位,每个内存单元都有一个编号,就相当于宿舍的门牌号,而这个编号就等于地址等于指针

(二)取地址操作符&

在c语言中创建变量本质上就是向内存申请空间,比如创建一个整型变量如下

int a=10;

一个整型变量占4个字节,就是向内存申请了4个字节,每个字节都有自己的地址,如下所示

那么如何取到a的地址呢,这里我们就在需要用到取地址操作符&,&在之前使用scanf函数也是经常用到,表示取这个数据的地址 ,怎么将地址打印出来呢,这里需要用到之前学到的占位符%p,比如将上述整形a的地址打印出来,如下所示

#include <stdio.h>

int main()

{

int a=10;
&a;//取出a的地址
printf("%p",&a);
return 0;
}

这里整型a明明占了4个字节,为什么只打印出来一个地址,因为&a取出的是4个字节中地址较小的字节的地址

(三)指针变量的创建和类型

在上述过程中我们得到了a的地址,那么为了后续使用,怎么样将它存储起来,这时候我们就可以将它存储在指针变量中 如下所示

int a = 10;
int* pa = &a;//取出a的地址,将其放入指针变量pa中

那么上述代码中的指针变量类型是什么,首先pa左边的int*,它在常规的整型变量中加了一个*,而*就表示pa是指针变量,而前面的int指pa指向的a是一个整型类型 那如果有一个char类型的b,那么该如何创建指针变量呢?如下所示

char b='a';
char*pc=&b;//取出字符b的地址,将其放入指针变量pc中

(四)指针变量的使用

我们通过指针变量将地址给存储起来,那么又该如何使用呢? 这时候我们就需要用到解引用操作符*,具体操作如下所示

int a = 10;
int* pa = &a;
*pa;//解引用,通过pa中存放的地址,找到指向的空间,所以这里的*pa就相当于a
printf("%d", *pa);

打印出来的*pa就是a的值

也可以通过修改*pa的值来修改a的值,如下所示

可以看出,不仅*pa的值变成199,a的值也同样修改为199

(五)指针变量类型的意义

1.指针的解引用

下面我们通过两段代码来理解指针变量的意义

int a = 0x11223344;//整型a存放的是16进制的数字
int* pa = &a;
	* pa = 0;将整型a的4个字节改成0

原来a在内存中存放的值如下

修改完之后如下

可以看出将4个字节全部修改成0

然而当我们创建char类型的变量时

int a = 0x11223344;
char* pa = (char*) & a;
	* pa = 0;

可以看出只能将a的第一个字节改成0

所以指针的类型决定了指针解引用时的权限,char*类型就只能访问一个字节,而int*类型的指针就可以访问4个字节

2.指针+-整数

通过上述的例子我们可以得知指针类型的不同,访问的字节也不同,我们可以再举一例,如下方代码

int a = 10;
int* pa = &a;
char* pc = (char*)&a;
printf("&a=%p\n", &a);
printf("pa=%p\n", pa);
printf("pa+1=%p\n", pa+1);
printf("pc=%p\n", pc);
printf("pc+1=%p\n", pc+1);

我们可以看出,char类型的指针+1之后在原来的基础上地址只变化了一位,而int类型的指针+1之后则在原来的基础上变化了4位,所以可以得知,指针的类型决定了指针变化了多少位。

那么我们可以再做个练习,用指针将数组中的元素依次打印出来,如下代码所示

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

}

pa表示的是取的是arr数组中第一个元素的地址,那我们只需要依次求出arr数组中元素的地址,再使用解引用符号*,我们就可以依次得出arr数组中的元素

3.指针+-指针

用以下代码举例

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* pa = &arr[0];
int* pc = &arr[9];

printf("%d", pc-pa);

指针-指针最终得到的结果就是两个指针(地址)之间的元素个数

⚠️:指针+-指针必须指向的是同一内存空间,像上方的代码中,指向的都是arr数组,下方代码为错误示范

int arr[4] = { 1,2,3,4 };
char b = 'e';
int* pa = &arr[2];
char* pc = &b;
printf("%d", pc - pa);

我们可以用指针-指针来求字符串长度,在之前,不用指针如何求字符串长度的呢,我们需要用到strlen函数,并且strlen函数的返回值是size_t,且需要头文件<string.h>,如下所示

#include <stdio.h>
#include <string.h>

int main()

{
	char ch[] = "abcde";
	size_t len = strlen(ch);
	printf("%d", len);


	return 0;
}

那么我们现在知道指针-指针就是两个指针之间的元素个数,那么我们可以分别求出字符串长度中第一个元素的地址,和’/0’的地址,将两个指针(地址)相减,就能得到字符串长度了,如下代码所示

size_t my_strlen(char* p)//指针接受参数
{
	char* start = &p[0];//start取ch数组第一个元素的地址
	while (*p != '\0')
	{
		p++;
	}
                       //p最终变成\0的地址
	return p - start;
}

int main()

{
	char ch[] = "abcde";
	size_t len = my_strlen(ch);//函数传递的是ch数组,其实ch又代表ch数组中第一个元素的地址
	printf("%d", len);         //所以传递的是地址,需要用指针来接受参数
	return 0;
}
4.指针的关系运算

两个指针比较大小,我们依旧拿我们最熟悉的题目举例,打印出数组中的每个元素,如下代码所示

int main()

{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* pa = arr;
	int* pc = &arr[sz];
	while (pa < pc)
	{
		printf("%d ", *pa);
			pa++;
	}

	return 0;
}

上述代码中,pa表示第一个元素的地址,而pc表示数组中的第十个元素的后一位的地址,不是数组内的,所以当pa<pc时,解引用打印出元素,再通过pa++,依次打印后面的元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值