[C语言] 初识指针

■指针的概念
■指针的基本类型 
■野指针
■指针和数组
■二级指针
■指针运算

**

一.指针的概念

**
指针也就是内存地址,指针变量是用来存放内存地址的变量,描述了数据在内存中的位置,标示了一个占据存储空间的实体,在这一段空间起始位置的相对距离值。在 C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。

**

二.指针的基本类型

1.指针变量决定了:指针进行解引用操作时可以访问几个字节(权限)

char*: 解引用时访问一个字节
int : 解引用时访问四个字节
double
:解引用时访问8个字节
在这里插入图片描述
在这里插入图片描述


int main()
{
	int a = 0x11223344;
	int*pa = &a;
	*pa = 0;


	/*char* pc = &a;
	*pc = 0;*/

	return 0;
}

2.指针类型决定了指针的步长,及(向前,向后,走一步多大距离)

int* 指针加1,表示跳过一个整型,意思是向后走4个字节;
char指针加1,表示跳过一个字符,意思是向后走1个字节;
double
指针加1,表示跳过一个double,意思是向后走8个字节;
short*指针加1,向后走2个字节;
在这里插入图片描述


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

	printf("pa=%p\n", pa);
	printf("pc=%p\n", pc);

	printf("pa+1=%p\n", pa -1);
	printf("pc+1=%p\n", pc -1);

	return 0;
}在这里插入代码片

**

三.野指针

**
野指针产生的原因(C语言中常见)
1.局部指针变量没有初始化

#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
    *p = 20;
 return 0;
}

2.指针越界访问

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    int *p = arr;
    int i = 0;
    for(i=0; i<=11; i++)
   {
  //当指针指向的范围超出数组arr的范围时,p就是野指针
        *(p++) = i;
   }
    return 0;
}

3.就是指针指向的空间未释放

常见的还有以下:


/*int main()
{
	int* p;//p就是野指针
	*p = 20;

	return 0;
}*/



int main()
{
	int arr[10] = {0};
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (i = 0; i <= sz; i++)
	{
		*p = i;
		p++;
	}

	return 0;
}

在这里插入图片描述

如何规避野指针
1.定义创建一个指针变量时一定要记得初始化
2.动态开辟的内存空间,free()释放内存后,一定要马上将对应的指针置为NULL空指针
3.不用再函数中返回栈空间的指针(地址)或局部变量的地址
4.注意在动态开辟内存后,对其返回值做合理判断,判断其是否为空指针

#include <stdio.h>
int main()
{
    int *p = NULL;
    //....
    int a = 10;
    p = &a;
    if(p != NULL)
   {
        *p = 20;
   }
    return 0;
}

**

四.指针和数组

首先我们以如下例子来举例:

#include <stdio.h>
int main()
{
 int arr[5] = {1,2,3,4,5};
    printf("%p\n", arr);
    printf("%p\n", &arr[0]);
    return 0;
}

运行结果如下:
在这里插入图片描述
我们就可以得出结论:数组就是首元素地址,数组名是数组第一个元素的地址,也是数组的首地址。
*

而以下情况除外:
1.&数组名 ----->表示的是整个数组
2.sizeof数组名 ----->计算的是整个数组的大小

五.二级指针

把一个指向指针变量的指针变量称为多级指针变量,对于指向处理数据的指针变量称为一级指针变量,简称一级指针,而把指向一级指针变量的指针变量称为二级指针变量,简称二级指针
在这里插入图片描述

对于二级指针的运算有:

1.*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .

int b = 10;
*ppa = &b;//等价于 pa = &b;

2.**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .

**ppa = 10;
//等价于*pa = 10;
//等价于a = 10;

六.指针运算

有下三种情况:

指针± 整数
指针-指针
指针的关系运算

6.1 指针±整数

#include <stdio.h>  
  
int main()  
{  
    int arr[10] = {1,2,3,4};  
    int *p = arr;  
    *p = 10;
    printf("%d\n",*p);  
    p++;
    *p = 20;  
    printf("%d\n",*p); 
 
    return 0;  
}  

结果为:
在这里插入图片描述
6.2指针-指针

int main()
{
	//两个指针相减的前提是:指针指向的同一块连续的空间
	int arr[10] = {0};
	printf("%d\n", &arr[9] - &arr[0]);
	printf("%d\n", &arr[0] - &arr[9]);

	int a = 10;
	char c = 'w';
	printf("%d\n", &a - &c);//err

	return 0;
}

6.3指针的关系运算

for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
    *vp = 0;
}

实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

总结:指针可以相减,也可以和立即数加或者减,两个指针相减可以理解为两个指针的距离,但是两个指针相加后将会是一个毫无意义的地址。最后,希望对大家有所帮助!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

起飞的风筝

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

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

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

打赏作者

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

抵扣说明:

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

余额充值