【C语言】初阶指针

1.指针的定义

指针就是一个变量,是一个用来专门储存地址的变量。比如在一个走廊里,两侧有很多房间,每个房间都挂有门牌号,门牌号就是每个房间的地址,通过门牌号可以找到指定的房间。指针就相当于是用来存放这些门牌号的变量,通过指针就可以找到以它为地址的内存单元。

用代码来说

int main()
{
	int a = 0;//在内存中开辟一块空间
	int* p = &a;//取出a的地址,把a的地址储存在p变量中,p就是一个指针变量
	return 0;
}
  • 如何给内存单元编地址?

机器分为32位和64位,就32位的机器来说,有32根地址线,每根电线都产生一个正电或负电的电信号(用1或0表示),那么32根地址线产生的地址就会是:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 0000001


11111111 11111111 11111111 11111111
这里就会有2的32次方个地址,若给一个单元赋为1个字节,那么2^32byte == 4GB,有4G的空闲区域进行编址.

总结
1.在32位的机器上,地址是由32个0或1组成的,则地址就要用4个字节的空间来储存,则一个指针变量的大小就是4个字节;64位的机器的指针变量大小就是8个字节

2.指针类型

我们都知道,变量有不同的类型,那么指针也有不同的类型

int main()
{
	int a = 10;
	int *pa = &a;
	char *pb = &a;
	float *pc = &a;
	short *pd = &a;
	double *pe = &a;
	printf("%d",sizeof(int *));//4
	printf("%d",sizeof(char *));//4
	printf("%d",sizeof(float *));//4
	printf("%d",sizeof(short *));//4
	printf("%d",sizeof(double *));//4  所有的指针变量的大小都是4
}
  • 既然指针变量不管是什么类型大小都是4个字节,那么指针变量和类型有什么关系呢

3.指针类型的意义

  • 指针±整数
# include <stdio.h>
int main()
{
	int a = 0;
	int *pa = &a;
	char *pc = &a;
	printf("%p\n", pa);
	printf("%p\n", pa+1);
	printf("%p\n", pc);
	printf("%p\n", pc+1);
	return 0;
}

在这里插入图片描述

说明指针类型决定了向后走一步能走多远(步长)

  • 整型指针
#include<stdio.h>
int main()
{
 int a = 0x11223344;//十六进制,
 int *pa = &a;//指针变量pa接收a的地址
 *pa = 0;//指针变量进行解引用操作,将a的地址改为0,此时解引用访问了4个字节
 return 0;
}

在这里插入图片描述

  • 字符指针
#include<stdio.h>
int main()
{
 int a = 0x11223344;//十六进制
 char * pc = &a;//将a的地址放到pc里面去
 *pc = 0;//指针变量进行解引用操作,将a的地址改为0,此时解引用只访问了0个字节
 return 0;
}

在这里插入图片描述

说明指针类型的另一个意义是指针解引用的权限有多大
比如,如果想从当前地址向后访问4个字节,那么就把这个地址放到int 型指针里;如果想从当前地址向后访问1个字节,就把这个地址放到char类型指针里

4.野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

野指针出现的原因

1.指针未初始化

int main()
{
	int *p;//指针未初始化,默认随机值,造成野指针
	*p = 0;//非法访问内存
	return 0;
}

2.指针越界访问

int main()
{
	int arrr[10] = { 0 };
	int *p = arr;
	int i = 0;
	for (i = 0; i <= 10;i++)
	{
		*p = i;
		p++;//当指针指向的范围超出数组arr的范围时,就会造成越界访问,这时p就是野指针
	}
	return 0}

3.指针指向的空间释放

int *test()
{
	int a = 10;
	return &a;//当调用完函数的时候,临时开辟的a的变量的空间释放,p成为野指针
}
int main()
{
	int *p = test();
	*p = 20;
	return 0;
}

5.规避野指针的方法

  1. 指针初始化

当指针变量p不知道应该初始化为什么地址的时候,直接初始为NULL (int *p = NULL)

  1. 小心指针越界
  2. 指针指向的空间释放时,及时放置NULL
  3. 指针使用之前检查有效性

6.指针和数组

  1. 首先,我们需要直到数组名是什么
    eg:
int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	return 0;
}

在这里插入图片描述

可见数组名和数组首元素地址是一样的
因此可以看下面一段代码

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

在这里插入图片描述

从这里我们可以看出,p+i 其实就是arr数组下标为i的地址,既然这样,我们就可以用指针直接访问数组

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

在这里插入图片描述

7.二级指针

二级指针就是存放指针变量地址的变量

在这里插入图片描述

8.指针数组

我们知道,数组有整型,有字符类型,那么也有指针类型
整型数组里存放的数据类型是整型,字符类型数组存放的数据类型是char 型,那么指针数组存放的数据类型都是指针类型。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小明会开拖拉机

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

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

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

打赏作者

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

抵扣说明:

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

余额充值