【初阶】C语言指针详解——指针必备的7大知识点

这篇具有很好参考价值的文章主要介绍了【初阶】C语言指针详解——指针必备的7大知识点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本篇文章我们来了解C语言中指针的相关内容,对于指针可以说是C语言学习中较难理解的内容。本篇以了解指针为目的,以初识为导向,从表层入手,浅析C指针!

一、指针是什么

🍑1、浅谈指针

理解指针的 两个要点:

  1. 指针是内存中一个最小单元的编号,也就是地址
  2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:指针就是地址,口语中说的指针通常指的是指针变量。

🍑2、内存

学习指针首先要了解 内存:

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。(每个内存单元都有地址)就好比电脑是我们的学校,内存就是学校的一个宿舍楼,而一个内存单元就代表宿舍楼中的一个宿舍,而宿舍的门牌号就表示一个地址。

对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);那么32根地址线产生的地址就会是:232 也就是说32位机器能够产生2的32次方个地址。每个地址标识一个字节,那我们就可以给 (2^32^Byte == 2^32^/1024KB == 2^32^/1024/1024MB==2^32^/1024/1024/1024GB == 4GB) 4G的空间进行编址。同理64位机器,如果给64根地址线,那么将有能力管理2^32^×4GB的内存空间。

🍑3、指针变量

为了能够更好的访问内存空间,我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量。

📝例如:

#include <stdio.h>
int main()
{
 int num = 10;//在内存中开辟一块空间
 int *p = &num;//这里我们对变量a,取出它的地址,可以使用&操作符。
    //num变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
	  中,p就是一个之指针变量。
 return 0; }

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享

总结:

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

二、指针和指针类型

🍑1、指针类型

我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?准确的说:有的。

C语言为我们提供了丰富的指针类型:

char  *pc = NULL;//字符指针 
int   *pi = NULL;//整形指针 
short *ps =NULL;//短整型指针 
long  *pl = NULL;//长整型指针 
float *pf = NULL;//单精度浮点型指针
double *pd = NULL;//双精度浮点型指针 
……

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享
其实:
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。

那指针类型的意义是什么?

🍑2、指针±整数

📝演示实例:

//演示实例
#include <stdio.h>
int main()
{
 	int n = 10;
 	char *pc = (char*)&n;
 	int *pi = &n;
 
 	printf("%p\n", &n);
 	printf("%p\n", pc);
 	printf("%p\n", pc+1);
 	printf("%p\n", pi);
 	printf("%p\n", pi+1);
 	return  0; 
 }

结果展示:
c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享
结论:

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

  1. char* 指针 + 1,意思是跳过一个字符,也就是向后走1个字节
  2. short* 指针 + 1,向后走2个字节
  3. int* 指针 + 1,意思是跳过1个整形,也就是向后走4个字节
  4. double* 指针 + 1,意思是跳过一个double,也就是向后走8个字节
  5. ……

🍑3、指针的解引用

📝演示实例:

//演示实例
#include <stdio.h>
int main()
{
 	int n = 0x11223344;
 	char *pc = (char *)&n;
 	int *pi = &n;
 	*pc = 0;   //重点在调试的过程中观察内存的变化。
 	*pi = 0;   //重点在调试的过程中观察内存的变化。
 	return 0; 
 }

调试结果:
c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享
结论:

指针类型决定了:指针解引用操作的时候,访问几个字节(权限)

  1. char* 的指针解引用访问1个字节
  2. int * 的指针解引用访问4个字节
  3. double* 的指针,解引用访问8个字节
  4. ……

三、野指针

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

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享

🍑1、野指针成因

🌳(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;
}

注释:当指针指向的范围超出数组arr的范围时,p就是野指针

🌳(3) 指针指向的空间释放

int* test()
{
	int num = 100;
	return &num;//出了函数,这块内存就不属于我们了,还给了操作系统
}

int main()
{
	int* p = test();
	*p = 200;
	return 0;
}

注释:变量num为局部变量,生命周期从创建开始到出test函数结束,test函数调用结束后num会将空间还给操作系统,此时回到主函数p的地址已经被释放,此时p就是野指针。

🍑2、如何规避野指针

  1. 指针初始化(已知指向时明确初始化;未知初始化为NULL)
  2. 小心指针越界
  3. 指针指向空间释放,及时置NULL
  4. 避免返回局部变量的地址
  5. 指针使用之前检查有效性

检查指针有效性:
原理:空指针NULL位于内核区域不能直接访问。

#include <stdio.h>
int main()
{
    int *p = NULL;//未知指向初始化为NULL
    int a = 10;
    p = &a;//明确初始化
    if(p != NULL)//为空指针不访问(无效指针)
   {
        *p = 20;//不为空再访问
   }
    return 0; 
}

四、指针运算

🍑1、指针± 整数

📝例如:通过指针加减整数遍历数组元素

int main()
{
	double arr[5] = {0};
	double* p = arr;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%lf ", *(p + i));
	}

	return 0;
}

🍑2、指针的关系运算

📝例如:通过指针初始化数组

#define N_VALUES 5
int main()
{
	float values[N_VALUES];
	float* vp;
	for (vp = &values[N_VALUES]; vp > &values[0];)
	{
		*--vp = 0;
	}
}

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享

代码简化, 这将代码修改如下:

#define N_VALUES 5
int main()
{
	float values[N_VALUES];
	float* vp;
	for (vp = &values[N_VALUES - 1]; vp >= &values[0]; vp--)
	{
		*vp = 0;
	}
}

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享
实际在绝大部分的编译器上以上两种写法都是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

标准规定:

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与 指向第一个元素之前的那个内存位置的指针进行比较。

🍑3、指针-指针

注释:指针和指针相减的绝对值等于指针和指针之间元素的个数。|p2-p1|==p1p2间元素个数

#include<stdio.h>
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;
}

补充:指针+指针没有意义

五、指针和数组

区别:
数组和指针不是一个东西。
数组能够存放一组数,连续的空间,数组的大小取决于元素个数。
指针是一个变量,是存放地址的。
联系:
数组名是地址(指针) 数组名把首元素的地址,交给一个指针变量后,可以通过指针来访问数组

📝通过指针和数组的联系,我们可以利用指针的偏移和解引用访问数组中的元素:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}
//输出:1 2 3 4 5 6 7 8 9 10

六、二级指针

🍑1、二级指针详解

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?答案是:二级指针

int main()
{
	int a = 10;//
	int *pa = &a;//pa就是指针变量,一级指针变量,表示指针指向的a是int
	int* *ppa = &pa;//ppa就二级指针,表示pp指向的p的类型是int*
	return 0;
}

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享

二级指针的运算:

1、*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa
int b = 20;
*ppa = &b;//等价于 pa = &b;

2、**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享

🍑2、多级指针

我们将问题故意复杂化一点,你想成为五星程序员吗?

#include <stdio.h>
int main()
{
    int n = 123;                        // int 
    int *oneStar = &n;                  // int *
    int **twoStar = &oneStar;           // int **
    int ***threeStar = &twoStar;        // int ***
    int ****fourStar = &threeStar;      // int ****
    int *****fiveStar = &fourStar;      // int *****

    printf("n = %d\n", *****fiveStar);  // 五次取值,还原为int
    return 0;
}

七、指针数组

🍑1、初识指针数组

指针数组是指针还是数组?
答案:是数组。是存放指针的数组。

int main()
{
	//整型数组-存放整型的数组
	int arr[10];
	//字符数组-存放字符的数组
	char arr2[5];
	//指针数组-存放指针的数组
	int* arr3[5];//存放整型指针的数组
	char* arr4[6];//存放字符指针的数组

	return 0;
}

📝例如:

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享

🍑2、指针数组的使用

📝用一维数组模拟一个二维数组:

int main()
{
	//用一维数组模拟一个二维数组
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int arr4[] = { 4,5,6,7,8 };

	int* arr[4] = {arr1, arr2, arr3, arr4};//用指针数组管理一维数组
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

总结

本篇为C指针初阶内容,向大家系统的介绍了C指针的相关内容,希望看完本文能够对C指针有一个更加全面的认识。老铁们,我们下期再见!😊

c语言指针知识点总结,『C语言』初阶+进阶,c++,c语言,C指针,学习,经验分享文章来源地址https://www.toymoban.com/news/detail-786164.html

到了这里,关于【初阶】C语言指针详解——指针必备的7大知识点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 产品经理之基础必备知识点

    目录 前言 一.用户画像         1.1含义        1.2 举例说明 二.MVP(最小可行产品)     1.1含义     1.2 优缺点 三.体验地图         3.1 含义         3.2 举例说明 四.产品路线图         4.1 含义         4.2 举例说明 五.用户故事         5.1 含义         5.2 举例 六.用户

    2024年01月18日
    浏览(48)
  • 面试必备之模电知识点汇总

    1、HC为COMS电平,HCT为TTL电平 2、LS输入开路为高电平,HC输入不允许开路,HC一般都要求有上下拉电阻来确定 输入端无效时的电平。LS却没有这个要求 3、LS输出下拉强上拉弱,HC上拉下拉相同 4、工作电压:LS只能用5V,而HC一般为2V到6V 5、CMOS可以驱动TTL,但反过来是不行的。

    2024年03月17日
    浏览(54)
  • C++知识点 -- 智能指针

    对于上面的场景,p1和p2在new申请空间后,div函数如果出现了除0错误,那么程序就会抛出异常,跳到接受异常的程序段继续执行,p1和p2申请的空间就没有被正常释放,造成了内存泄漏; 这种场景我们就可以使用智能指针来解决空间的释放问题。 RAII(Resource Acquisition Is Initia

    2024年02月03日
    浏览(60)
  • 【网络工程师必备知识点】eNSP命令大全【建议收藏】

           这里整理了一些华为认证考试会用到的资料,资料打包好给大家放在评论区了,有需要的小伙伴留言“学习”即可获取呀,包括40g学习视频、真题题库加讲解、面试题库加答案、简历模板、网络技术学习路线和思维导图,已经帮助了很多小白成功上岸!  

    2024年02月08日
    浏览(54)
  • AIGC必备知识点:你不可不知的CNN(卷积神经网络)-知识全解析!

    Look!👀我们的大模型商业化落地产品 📖更多AI资讯请👉🏾关注 Free三天集训营助教在线为您火热答疑👩🏼‍🏫 大家在谈论的卷积神经网络究竟是什么?(Convolutional Neural Network,CNN)是一类主要用于计算机视觉领域的深度学习算法,它被广泛地运用于包括图像和视频识别、

    2024年01月17日
    浏览(41)
  • 【C】指针——知识点大全(详细,简洁,含例题)

      前言: 大家好,这里是 YY ;此篇博客主要是 指针的知识点 ;包含 【一二级指针】【字符指针】【指针数组】【数组指针】【以上知识的实际应用】【函数指针】【函数指针数组】 PS:创作不易,每个知识点都有 例题或者图 帮助理解;如果对你有帮助,希望能够得到您的

    2024年02月05日
    浏览(46)
  • Android OpenCV(四十三),Android程序员面试必备的知识点

    标志位 值 含义 GC_INIT_WITH_RECT 0 使用提供的矩形初始化状态和掩码。 之后根据算法进行迭代更新 GC_INIT_WITH_MASK 1 使用提供的掩码初始化状态。 可以组合使用GC_INIT_WITH_RECT和GC_INIT_WITH_MASK。 然后,使用GC_BGD自动初始化ROI之外的所有像素。 GC_EVAL 2 表示算法应该恢复 GC_EVAL_FREEZE_

    2024年04月09日
    浏览(54)
  • 什么是预训练Pre-training—— AIGC必备知识点,您get了吗?

    Look!👀我们的大模型商业化落地产品 📖更多AI资讯请👉🏾关注 Free三天集训营助教在线为您火热答疑👩🏼‍🏫 随着人工智能(AI)不断重塑我们的世界,其发展的一个关键方面已经成为现代机器学习模型的支柱:预训练。在本篇文章中,我们将探讨预训练的概念,它在人工智

    2024年02月02日
    浏览(39)
  • Android 开发必备知识点及面试题汇总(Android+Java+算法+性能优化+四大组件……),腾讯安卓开发面试

    5.请介绍下 AsyncTask的内部实现,适用的场景是 AsyncTask 内部也是 Handler 机制来完成的,只不过 Android 提供了执行框架来提供线程池来 执行相应地任务,因为线程池的大小问题,所以 AsyncTask 只应该用来执行耗时时间较短的任务, 比如 HTTP 请求,大规模的下载和数据库的更改不

    2024年04月15日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包