C初阶——浅谈指针

目录

一、指针是什么?

二、指针类型

三、野指针

1.野指针成因

2.如何避免野指针

四、指针运算

1.指针+-整数

2.指针-指针

3.指针的关系运算

五、二级指针

六、指针数组


一、指针是什么?

指针理解的两个要点:

指针是内存中的一个最小内存单元的编号,也就是地址(指针就是地址);

平时我们口语说的指针,通常指的是指针变量,是用来存放内存地址的变量。

所以,指针就是地址,通常口语中所说的指针大多指的是指针变量。

为了能够有效的访问到内存中的每个单元,就把内存单元进行了编号,这些编号被称为内存单元的地址。

内存被划分成一个个小的内存单元,一个基本的内存单元的大小是一个字节。

我们可以通过&变量,取出变量的内存起始地址,把地址存放到一个变量当中,这个变量就是指针变量。 

int a=10;
int* p=&a;//p为指针变量
//int表示p所指向的对象a的类型是int,*表示p为指针变量

指针变量,用来存放地址的变量(注意:存放在指针变量中的值都被当作了地址来处理)

那么内存是如何编址的呢?

对于32位机器来说,假设有32根地址线,每根地址线在寻址的时候会产生高电平和低电平,也就是电信号1/0,那么32根地址线产生的地址就会是:

00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
 
...      ...      ...      ...
 
 
01111111 11111111 11111111 11111111
10000000 00000000 00000000 00000000
10000000 00000000 00000000 00000001
 
...      ...      ...      ...
 
11111111 11111111 11111111 11111101
11111111 11111111 11111111 11111110
11111111 11111111 11111111 11111111

这里就会有2的32次方个地址编号,

因为一个内存编号管理一个字节大小的空间,所以32位机器可以管理2^32个字节的内存空间,

换算成GB也就是:

2^32Byte == 2^32 / 1024KB == 2^32 / 1024 / 1024MB == 2^32 / 1024 / 1024 / 1024GB == 4GB,

同样的方法算出,对于64位机器,可以管理8GB大小的内存空间。

(注意这里不要将指针变量的大小和指针管理一块空间的大小混淆!指针变量的大小在32位平台是4个字节,在64位平台是8个字节,而指针也就是一块内存单元编号,可以管理一个字节的空间)

【总结】

指针变量是用来存放地址的,指针是唯一标示一块内存空间的;

指针变量的大小在32位平台是4个字节,在64位平台是8个字节。

二、指针类型

我们都知道变量都有不同的类型,如整形、浮点型等。那么指针变量有没有类型呢?

准确的说:有的。

可是变量的类型是用来决定变量开辟空间的大小,指针变量的类型都是4/8个字节,那还分不同指针类型干什么?

这就要明白指针类型的意义是什么

意义一:

指针类型决定了指针在解引用的时候一次能访问几个字节(也叫指针的权限)。 

意义二:

指针类型决定了指针向前或向后走一步走多大距离(+-整数),单位是字节!

三、野指针

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

1.野指针成因

指针未初始化;

指针越界访问;

指针指向的空间已经释放(特别易错)。

(1)指针未初始化

int* p;//未初始化,p为随机值,指向不可知

(2)指针越界访问

//最常见的就是数组越界访问 
#include<stdio.h>
 
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
    int* p=arr;
	int i = 0;
	for (i = 0; i < 12; i++)//当i大于九时,数组越界
	{
		*(p+i) = 1;
        p++;
	}
 
	return 0;
}

(3)指针指向的空间已经释放

#include<stdio.h>
 
int* test()
{
	//局部变量a一旦出了本函数范围就会被销毁,内存空间的使用权限被收回了
	int a = 100;
	return &a;//返回a的地址
}
 
int main()
{
	int* p = test();
	//指针p用来接收a的地址,但是test函数调用完毕后,分配给a的内存空间也就被收回了
	//导致p成为了野指针
	printf("%d\n", *p);
 
	return 0;
}

2.如何避免野指针

  1. 指针初始化;
  2. 小心指针越界;
  3. 指针指向的空间释放即时置为NULL;
  4. 避免返回局部变量的地址(野指针的成因3);
  5. 指针使用之前需要检查其有效性。

举个例子

#include <stdio.h>
int main()
{
  int *p = NULL;//对指针进行初始化
  //....
  int a = 10;
  p = &a;
  if(p != NULL)//进行有效性判断
 {
    *p = 20;
 } 
  p = NULL;//使用完,将p置为NULL
  return 0;
}

四、指针运算

1.指针+-整数

前面我们说过指针类型决定了指针向前或向后走一步走多大距离(+-整数)

所以,一个整形指针加1,就是跳过一个整形,指向下一个整形。

其他类型,同理。

2.指针-指针

指针-指针其实表示的是两个指针中间的元素个数注意,不是中间有几个字节。

【注意】:

使用指针-指针运算的时候,前提是两个指针指向的是同一块内存空间,

那何为指向同一块内存空间呢?最典型的例子就是数组

3.指针的关系运算

指针的关系运算,也就是指针比较大小,指针怎么比较大小呢,前面我们说过,指针就是地址,所以指针比较大小比较的是地址的大小,也就是说比较的是地址的高低。

五、二级指针

指针变量也是变量,是变量就需要在内存中开辟空间也就会有地址,那么指针变量的地址该怎么存放呢

指针变量的地址存放到二级指针中。

int a = 10;
int* pa = &a;
int** ppa = &pa;

六、指针数组

指针数组是数组,是用来存放指针变量的数组

int* arr[5];//arr是一个数组,有五个元素,每个元素为整形指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

theonly_Love

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

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

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

打赏作者

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

抵扣说明:

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

余额充值