指针的深度理解(1)

简介: 指针的深度理解(1)

指针初概念

首先我们要先理解指针的概念,我们都知道CPU处理数据时,需要的数据是从内存中读取的,内存有8GB  16GB  32GB等,那么我们要知道GB是一个大的单位,但内存也分为一个个内存单元,每个存单元取一个字(byte),一个字节又等于8个比特位(bit),一个比特位可以储存2进制的0或1,计算机中内存单元都有一个编号,C语言中把这个地址也叫做指针!我们也可以这么理解:

内存单元的编号==地址==指针

下面我们来讲解

指针变量和取地址操作符(&)解引用操作符(*)

指针变量其实就是我们平常说的指针,那指针变量用来干嘛呢,答案是用来储存地址的,这时我们要想将一个地址存到指针变量中,我能便需要用到取地址操作符“&”,大家可以看下面代码:

#include<stdio.h>
int main()
{
  int i = 10;
  int* pa = &i;
  printf("%p", pa);
 
  return 0;

这样一看就知道i的地址已经储存在指针变量pa上了。


需要注意的是指针变量也是一种变量,它的大小在32位机器中指针变量占4个字节,64位机器中占8个字节!由于地址线的不一样指针变量的大小就会有所不一样,我们可以看下面代码:

#include<stdio.h>
int main()
{
  int i = 10;
  int* pa = &i;
  printf("%d", sizeof(pa));
  return 0;
}


现在来讲讲解引用操作符“*”的作用,计算机方面知识比较抽象,我们可以通过类比现实例子:好比在现实生活中我们可以使用一个地址去到一个房间里拿存放的东西,指针也一样,我们也可以通过指针找到里面的东西那么,“*” 就可以理解为动词“找”。下面用代码来给大家看一下:

#include<stdio.h>
int main()
{
  int i = 10;
  int* pa = &i;
  printf("%d", *pa);
  return 0;
}

如上面可以看出*pa打印出来是10也就是原本给i赋的值!若果想改变i的值也可以通过指针变量来改变

#include<stdio.h>
int main()
{
  int i = 10;
  int* pa = &i;
  *pa = 20;
  printf("%d", *pa);
  return 0;
}


下面我们在来讲讲“指针的类型“

指针的类型

指针类型无非就是相当我们之前学过的类型后加个“*”号,例如:

char*    int*     float*     long*等等

那么我们可以很容易想到int类型的地址就放到int*类型的指针变量里去,当然如果你非要把int类型的地址放到char*那里去,只要进行类型强制转换后,也是可以的,但是,当你对指针进行操作时那么就会出现偏差了!下面看一下例子:

这是指针变量存放对应的变量地址时改变内容时i的内存变化:

#include<stdio.h>
int main()
{
  int i = 0x00112233;
  int* pa = &i;
  *pa = 1;
  printf("%d", *pa);
  return 0;
}

这是将int i的地址放到char* pa指针变量上的情况

#include<stdio.h>
int main()
{
  int i = 0x00112233;
  char* pa = &i;
  *pa = 1;
  printf("%d", *pa);
  return 0;
}

通过这个代码我们可以理解,指针类型就是代表步数的跳过不一样,int*类型的指针变量进行+1,便是跳过4个字节去访问下一个地址。char*类型的指针变量如果进行+1,便是跳过个字节去访问下一个地址。这说明int*指针解引用只能访问一个字节,int*指针解引用就能访问4个字节,竟然这么讲那么float和int类型变量都是占4个字节,那么他们的指针是不是就没有区别呢,答案肯定是否定的,既然指针变量的类型有区别,那么他们的作用肯定是不一样的,那么它们两有啥不一样呢——其实就是他们两在内存单元中的储存方式是不一样的,操作起来时某些地方肯定是会出现偏差的。

const修饰指针:

我们都知道变量是可以被修改的,如果把一个变量的地址交给一个指针变量,通过指针也可以修改这个变量,但如果我们希望通过指针变量不能被修改呢,这时const的作用就体现出来了,下面写几个代码,让大家更好理解:

这里注意编译器下方有红波浪线的地方便得出下面结论:

const在*的左右两边效果是不一样的

  • const如果放在*的左边,修饰的是指针指向的内容,保证了指针指向的内容不能够通过指针来改变,但是指针变量本身的内容可变(即它可以存放另一个变量的地址)

const如果放在*的右边,修饰的是指针变量本身,保证了指针变量内容不能被修改,但是指针变量指向的内容,可以通过指针改变。


野指针:

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

野指针生成的原因有:

  • 指针未初始化
#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
 *p = 20;
 return 0;
}
  • 指针越界访问
#include<stdio.h>
int main()
{
int arr[5] = {0};
 int *p = &arr[0];
 int i = 0;
 for(i=0; i<=10; i++)
 {
 //当指针指向的范围超出数组arr的范围时,p就是野指针
 *p++ = i;
 }
 return 0;
}
  • 指针指向空间释放
#include <stdio.h>
int* test()
{
 int n = 100;
 return &n;
}
int main()
{
 int*p = test();
 printf("%d\n", *p);
 return 0;
}

野指针在一定程度上会使我们无法正常通过指针变量进行修改所指向对象所以我们要规避野指针,规避的方法有:

  • 指针初始化
  • 避免指针越界
  • 指针变量不再使用时,及时置NULL,使用之前检查有效性

指针的运算:

  • 指针加减整数
#include<stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int n = sizeof(arr)/sizeof(arr[0]);
 for(i=0; i<n; i++)
 {
 printf("%d ", *(p+i));//p+i 这⾥就是指针+整数
 }
 return 0;
}

指针加减整数即在一连串的地址中往后或往前指向另一个地址,就如上数组中每个下标对应的数组元素会有各自的地址且连在一起 :

  • 指针减指针

指针减指针就可以理解为为同一块区域内的的两个指针的距离:

#include<stdio.h>
int main()
{
  int arr[10] = { 0 };
  int* i = &arr[0];
  int* j = &arr[9];
  printf("%d", j - i);
  return 0;
}

这样就可以证明上述所说。通过这个知识我们便可自己写一个stren函数如下

#include <stdio.h>
int my_strlen(char *s)
{
 char *p = s;
 while(*p != '\0' )
 p++;
 return p-s;
}
int main()
{
 printf("%d\n", my_strlen("abc"));
 return 0
}

指针的关系运算

指针的关系运算可以用一个数组理解为,后面元素的地址大于前面的地址,如下地址4是比前面3个地址都要打的:

对于这个知识点我们可以看下面的代码理解与之前大家创建另一个变量进行 i<sz有所不同呢

#include <stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 while(p<arr+sz) //指针的⼤⼩⽐较
 {
 printf("%d ", *p);
 p++;
 }
 return 0;
}

好了各位今天指针(1)先讲到这了,下期会有指针更多的·实际使用哦!喜欢的话可以关注期待哦

目录
相关文章
|
25天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
17天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
4天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
1天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
263 12
|
19天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
21天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2582 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
3天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
171 2
|
1天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
101 65
|
21天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1578 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
5天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
263 2