返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言指针必备基础全面覆盖
  • 220
分享到

C语言指针必备基础全面覆盖

2024-04-02 19:04:59 220人浏览 安东尼
摘要

目录前言一、指针是什么?1.数据在内存中的存储2.一个小的单元到底是多大?二、指针变量1.什么是指针变量2.指针类型3.指针类型的作用三、野指针1.什么是野指针2.野指针成因2.1.

前言

指针是C语言中的一个重要概念。正确而灵活的运用指针,可以使程序间接、紧凑、高效。每一个学习和使用C语言的人,都应当深入地学习和掌握指针。

提示:以下是本篇文章正文内容,下面案例可供参考

一、指针是什么?

指针是包含内存地址的变量,这个地址是内存中另一个对象(通常是另一个变量)的位置。例如如果一个变量包含另一个变量的地址,我们说第一个变量指向第二个变量。

相信大家看到上面这段话,可能有点懵,不急,我稍后再给大家解释。在这里,我先给大家讲述一下,数据在内存中是如何存储和读取的?

1.数据在内存中的存储

如果在程序中定义了一个变量,在对程序进行编译的时候,系统就会给这个变量分配内存单元。编译系统根据程序中的定义的变量类型,分配一定长度的空间

在这里插入图片描述

那么,这些字节在内存中被分配到哪里?我们如何找到呢?
为了解决这个问题,我们就给内存区的每一个字节一个编号,这个就是它们的“地址”。它相当于旅馆中的房间号,在地址所标志的内存单元中存放的数据则相当于旅馆房间中居住的旅客。

在这里插入图片描述

所以指针是个变量,存放内存单元的地址(编号)

2.一个小的单元到底是多大?

1、对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);

2根地址线上的电信号转换成数字信号用(1/0)表示,所以可能性
00000000000000000000000000000000–11111111111111111111111111111111
也就是有2^32 编号,说明可以管理2的32次方个单元
这里就有2的32次方个地址。

每个地址标识一个字节,那我们就可以给
(2^32Byte == 2^32/1024KB == 2^32 /1024/1024MB==2^32/1024/1024/1024GB == 4GB) 4G的空闲进行编址。

按照同样的方法,我们可以计算出64四位机器,下面就直接给结论了。

1、在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所 以一个指针变量的大小就应该是4个字节。
2、在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址

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

二、指针变量

1.什么是指针变量

思考一个问题,在编译器中,如何把3赋值给i这个变量中?

第一种作法,把3直接送到i所表示的单元中,例如“i=3”;


int main()
{
	int i=3;
	return 0;
}

第二种方法,把3送到变量p所指向的单元(即变量i的存储单元,也就是地址,如p=3,其中i表示p指向的对象)


int main()
{
	int i;
	//int i = 3;//第一种方法
	int *p = &i;//第二种方法
	//这里我们对变量a,取出它的地址,可以使用&操作符。
   //将i的地址存放在p变量中,p就是一个指针变量。
	*p = 3;
	printf("%d\n", i);
	return 0;
}

在这里插入图片描述

2.指针类型

思考一个问题:

把int型变量a和float型变量b先后分配到2000开始的存储单元中,&a和&b的信息完全相同吗?

答案是不相同的,因为虽然存储单元的编号相同,但他们的数据类型不同。

此外,还因为数据类型的不同,无法确定是从一个字节中取信息(字符数据),还是从两个字节取信息(短整型),抑或是从四个字节取信息(整型),不同的类型,存储方式是不一样的。

如果我们要将&num(num的地址)保存到p中,我们需要我们给指针变量相应的类型。

如下:


char  *pc = NULL;//har* 类型的指针是为了存放 char 类型变量的地址。
int   *pi = NULL;//int* 类型的指针是为了存放 int 类型变量的地址。
short *ps = NULL;//short* 类型的指针是为了存放 short 类型变量的地址
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;

这里可以看到,指针的定义方式是: 类型名 * 指针变量名 。

总结

C语言中的地址包括位置信息(内存编号,或称纯地址)和它所指向的数据的类型信息,或者说它是“带类型的地址”,如&a,一般称它位“变量a的地址”,但是确切地说,它是“整型变量a的地址”

3.指针类型的作用

作用一:

指针类型决定了指针解引用操作的时候,一次访问几个字节(访问内存的大小)


int main()

{	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;
	return 0;
}

在这里插入图片描述


int main()
{
	int a = 0x11223344;

	char* pc = &a;//int*
	*pc = 0;
	return 0;
}

在这里插入图片描述

指针类型的意义1

指针类型决定了指针解引用操作的时候,一次访问几个字节(访问内存的大小)
char* 指针解引用访问1个字节
int* 指针解引用访问4个字节

作用二:

指针类型决定了,指针±整数的时候的步长(指针±整数的时候,跳过几个字节)


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

	printf("%p\n", pa+1);//如果是整型指针int*,+1则跳过4个字节、
	printf("%p\n", pc+1);//char* 指针+1,跳过1个字节
	return 0;
}

在这里插入图片描述

三、野指针

1.什么是野指针

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

什么意思?举个例子
就是你捡到一把钥匙,但是不知道它可以开那道门。

2.野指针成因

2.1. 指针未初始化

指针没有初始化,里面放的是随机值


#include <stdio.h>
int main()
{ 
 	int *p;//局部变量指针未初始化,默认为随机值
    *p = 20;//通过p中存的随机值作为地址,找到一个空间,这个空间不属于我们当前的程序,就造成了非法访问
//如果非法访问了,p就是野指针
 return 0; }

2.2指针越界访问

指针越界造成野指针问题


int main()
{
	int arr[10] = 0;
	int i = 0;
	int * p = arr;

	for (i = 0; i <= 10; i++)//这里循环了11次,当指针指向的范围超出数组arr的范围时,p就是野指针
	{
		*p = 1;
		p++;
	}
	return 0;
}

2.3指针指向的空间释放

当一个指针指向的空间释放了,这个指针就变成野指针了


int* test()
{
	int a = 10;
	return &a;  //int *,生命周期,出来就销毁了
}
int main()
{
	int *p = test();
	//printf("不愧是你\n");//加入这里加了一条语句,下面的值就变了
	printf("%d\n", *p);//编译出10是因为编译器会对值做一次保留。所以能访问到上面函数不一定是对的
	return 0;
}

3.如何规避野指针

  • 指针初始化
  • 小心指针越界
  • 指针指向空间释放即使置NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性

//规避野指针
int main()
{
	int a = 10;
	int * p = &a;//1、明确初始化,确定指向

	int * p2 = NULL;//NULL本质是0,2、不知道一个指针当前应该指向哪里是,可以初始化位NULL
	//*p2 = 100;//err,对于空指针,是不能直接解引用的

	//如何规避? 
	if (p2 != NULL)//先判断是不是空指针
	{
		*p2 = 100;//这样才对
	}

}

四、指针运算

1.指针±整数


int main()
{
	float arr[5];
	float *p;
	for (p = &arr[0]; p < &arr[5];)
	{
		*p++ = 0;//对一个指针加1使它指向数组中的下一个元素,把指针指向的内容全部赋值给0
	}
	return 0;
}

在这里插入图片描述

也就说,如果加2使它向右移动2个元素的位置,依次类推。把一个指针减去2使它向左移动2个元素的位置。

2.指针-指针

1、指针减去指针的前提,是两个指针指向同一块区域
2、指针减去指针,得到数字的绝对值,是指针和指针之间元素的个数


int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	char ch[5] = { 0 };
	//printf("%d\n", &arr[9] - &ch[0]);//这种算法是错误的

	printf("%d\n", &arr[9] - &arr[0]);//算出的是元素的个数
	printf("%d\n", &arr[0] - &arr[9]);//
	//指针减去指针的前提,是两个指针指向同一块区域
	//指针减去指针,得到数字的绝对值,是指针和指针之间元素的个数

	return 0;
}

在这里插入图片描述

【注意】
指针与指针之间不能进行加法运算,因为进行加法后,得到的结果指向一个不知所向的地方,没有实际意义

什么意思,举个例子。

在这里插入图片描述

五、指针和数组

1.数组元素的指针

一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。

指针变量既然可以指向变量,当然也可以指向数组元素,也就是把某一元素地址放到一个指针变量中。

所谓数组元素的指针就是数组元素的地址

(1)用一个指针变量指向一个数组元素


int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	int* p;//定义p位指向整型变量的指针变量
	p = &arr[0];//把a[0]元素的地址赋给指针变量p
	return 0;
}

以上是使指针变量p指向a数组的第0号元素

在这里插入图片描述

2.通过指针引用数组元素

(1)下标法,如a[i]形式
(2)指针法,如*(a+i)

下标法:


int main()
{
	int arr[10];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", sz);
	printf("%p\n", arr);//数组名就是首元素地址
	//下标法
	printf("%p\n", &arr[0]);
	int* p=&arr[5];//整型地址放在整型指针上,从而让指针跟数组建立联系

	//数组名确实是首元素地址,
	//但是有两个例外
	//1.sizeof(数组名),这里的数组名不是首元素地址,是表示整个数组,计算的是整个数组的大小,单位是字节
	//2.&数组名,拿到的是整个数组的地址

	return 0; 
}

在这里插入图片描述

指针法:


int main()
{
	int arr[10];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	int* p=&arr[0];//整型地址放在整型指针上,从而让指针跟数组建立联系
	//指针法
	for (i = 0; i < sz; i++)
	{
		*(p + i) = i;// p+i 其实计算的是数组 arr 下标为i的地址。
	}
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0; 
}

在这里插入图片描述

一个小知识:


int main()
{

	int arr[10] = { 0 };
	arr;//数组名
	&arr[0];//取出首元素地址
	&arr;//取出整个数组的地址
	printf("%d\n", &arr[0]);
	printf("%d\n", &arr);
	return 0;
}

在这里插入图片描述

六、二级指针

指针变量的地址二级指针

什么意思?举个例子


int main()
{
	int a = 10;//4byte,向内存申请4个字节
	int* p=&a;//p指向a,称为一级指针

	int* *pp=&p;//pp就是二级指针,pp存放的是一级指针的地址
	* *pp = 20;//需两层解引用	
	printf("%d\n", a);
	//int** * ppp = &pp;//ppp就是三级指针
	return 0;
}

七、指针数组

存放指针的数组就是指针数组


int main()
{
	int arr[10];//整型数组,存放整型的数组就是整型数组
	char ch[5];//字符数组,存放字符的数组就是字符数组
	//指针数组,存放指针的数组就是指针数组
	//int*  整型指针的数组
	//char* 字符指针的数组

	int* parr[5];//整型指针的数组,存放的类型都是int*
	char* pc[6];//字符指针的数组
	return 0;
}

我们也可以用同样的方式来访问指针数组。
如下


int main()
{
	int a = 10;
	int b = 20;
	int c = 30;

	int * arr[3] = { &a, &b, &c };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d\n",*(arr[i]));
	}

	int *pa = &a;
	int *pb = &b;
	int *pc = &c;
	return 0;
}

在这里插入图片描述

最后

本文介绍的是指针的基础知识,往后还会继续深入讲解指针更深入的知识。此外,本文参考了谭浩强《C语言设计》(第五版),以及网上的部分资料,加之自己在学习听课时的笔记,梳理而成,花费了我很多心思。当文章写成之时,时间已过去4个多小时!

希望能对看到的大家有所帮助!

以上就是C语言指针必备基础全面覆盖的详细内容,更多关于C语言 指针的资料请关注编程网其它相关文章!

--结束END--

本文标题: C语言指针必备基础全面覆盖

本文链接: https://lsjlt.com/news/155420.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C语言指针必备基础全面覆盖
    目录前言一、指针是什么?1.数据在内存中的存储2.一个小的单元到底是多大?二、指针变量1.什么是指针变量2.指针类型3.指针类型的作用三、野指针1.什么是野指针2.野指针成因2.1....
    99+
    2024-04-02
  • C语言指针之必须要掌握的指针基础知识
    目录一、指针概述指针的创建指针的大小如何使用指针二级指针二、野指针形成野指针的原因如何规避野指针三、指针的基本运算指针± 整数指针-指针四、指针和数组五、指针数组总结一、指针概述 指...
    99+
    2024-04-02
  • C语言指针基础详解
    目录1.1:概述1.1.1:内存1.1.2:内存1.1.3:指针和指针变量1.2:指针基础知识1.2.1:指针变量的定义和使用1.2.2:通过指针间接修改变量的值1.2.3:指针的大...
    99+
    2024-04-02
  • c语言 指针零基础讲解
    1.指针是什么(可能有点难理解) 指针的是啥? 指针实际上就是地址,地址就是系统给定的编号,编号就是一个个内存单元。 在某种情况来说指针=地址=编号=内存单元。 指针就是地址,顾名思...
    99+
    2024-04-02
  • C语言超全面覆盖操作符知识点
    目录算术操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符算术操作符 主要是 (+ - * / %) 五种算数操作符。 1、除了 % 操作符之外,其他的几个操...
    99+
    2024-04-02
  • C语言基础指针详解教程
    目录1.1:概述1.1.1:内存1.1.2:内存1.1.3:指针和指针变量1.2:指针基础知识1.2.1:指针变量的定义和使用1.2.2:通过指针间接修改变量的值1.2.3:指针的大...
    99+
    2024-04-02
  • Go语言基础之指针
    区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。 要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。 Go语言中的指针 任何程序数据载入内存后,在内存都有他们的地址,这就是指针。而为了保存一...
    99+
    2023-08-30
    golang 开发语言 后端
  • C语言基础野指针与空指针示例分析
    目录一:野指针野指针的成因1. 指针未初始化2. 指针越界访问3 .指针释放后未置空规避野指针1. 初始化指针 2. 避免指针越界 3 避免返回局部变量的地址 4. 开辟的指针释放后...
    99+
    2024-04-02
  • 零基础详解C语言指针进阶
    目录前言1.字符指针例题 12.指针数组例题 23.数组指针3.1数组指针的定义3.2 &数组名与数组名3.3 数组指针的使用4.数组与指针在函数里的传参4.1 一维数组的传...
    99+
    2024-04-02
  • C语言基础知识点指针的使用
    目录一、指针的作用二、地址与指针三、指针变量四、数组与指针五、指针自加自减运算六、指向指针的指针七、指针变量作为函数形参八、函数指针九、函数指针数组十、指针的应用场景一、指针的作用 ...
    99+
    2024-04-02
  • C语言零基础讲解指针和数组
    目录一、指针和数组分析-上1.数组的本质2.指针的运算3.指针的比较4.小结二、指针与数组分析-下 1.数组的访问方式2.下标形式 VS 指针形式3.a 和 &a ...
    99+
    2024-04-02
  • C语言指针笔试题全面解析
    目录前言一、指针笔试题 1.题目如图:2.题目如图: 3.题目如图:4.题目如图:   5.题目如图:6.题目如图:7.题目如图:&...
    99+
    2024-04-02
  • C语言基础双指针移除元素解法
    本题方法:双指针。知识比较基础,思路简单 题目: 我的题解: int removeElement(int* nums, int numsSize, int val) { ...
    99+
    2024-04-02
  • c语言中指针零基础知识点有哪些
    小编给大家分享一下c语言中指针零基础知识点有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.指针是什么(可能有点难理解)指针的是啥?指针实际上就是地址,地址...
    99+
    2023-06-29
  • Go语言基础学习之指针详解
    目录1. 什么是指针2. 指针地址 & 指针类型3. 指针取值4. 空指针5. make6. new7. make 和 new 的区别8. 问题今天来说说 Go 语言基础中的...
    99+
    2022-12-30
    Go语言指针使用 Go语言指针 Go 指针
  • Python基础-你必备的语言技能包
    今天,我们正式开始数据分析课程的基础篇,Python 基础。 为什么是 Python 呢,在相关的开发语言调查中,使用过 Python 的开发者,大多数人都会把 Python 作为自己的主要语言。在数据分析领域,使用 Python 语言更是...
    99+
    2023-01-31
    技能 语言 基础
  • C语言从基础到进阶全面讲解数组
    目录1.基础知识2.数组的分类2.1按元素类型分类2.2按维数分类3.数组定义和初始化3.1 一维数组3.2 二维数组4.数组元素的引用方法5.字符数组的定义1.基础知识 C语言中使...
    99+
    2024-04-02
  • C语言全方位讲解指针的使用
    目录一、指针的概念1.1、变量和地址1.2、指针变量和指针的类型二、指针变量2.1、指针变量的定义及使用2.2、指针运算三、野指针3.1、概念:3.2、野指针的成因3.3、如何规避野...
    99+
    2024-04-02
  • C语言树与二叉树基础全刨析
    目录一、树的概念和结构1.1 树的概念1.2 树的结构 & 相关名词解释1.3 树的表示1.4 树的应用二、二叉树的概念 & 存储结构(重要)2.1 二叉树的概念2....
    99+
    2024-04-02
  • R语言学习Rcpp基础知识全面整理
    目录1. 相关配置和说明2. 常用数据类型3. 常用数据类型的建立4. 常用数据类型元素访问5. 成员函数6. 语法糖6.1 算术和逻辑运算符6.2. 常用函数7. STL7.1. ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作