C语言 _ 指针(超详解析 3分钟完全掌握 总结性讲解 经典通俗)

2023-11-01

 目 录

1.指针、指针变量及指针的大小

2.指针类型

3. 指针的解引用

4. 指针运算

  4.1指针+-整数

  4.2指针+-指针

5. 野指针

 5.1 为什么会有野指针

5.2 如何规避野指针

6. 指针和数组

7. 二级指针

  7.1二级指针的定义

8. 指针数组


1.指针、指针变量及指针的大小

  指针是编程语言中的一个对象,利用地址,它的值指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。用一句话概述:指针就是地址!

  指针变量:口语中说的指针通常指指针变量。指针变量就是存放内存地址的变量,保存的是指针的地址。

  我们来一小段代码加深下理解吧!

#include <stdio.h>

int main()

{

int num=1;//num会保存在内存中,并有他独一无二的地址

int *p = &num;//&操作符的作用是取地址。

  //这里取出num的地址存放在p变量中,p就是一个指针变量了。

return 0;

}

  那么一个指针能有多大呢?

  在32位的机器上,地址是32个0或者1组成二进制序列(1个0或1占1bit大小~32bit=4字节)那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节

  同理,在64位机器上,地址是64个0或者1组成二进制序列,那一个指针变量的大小是8个字节,才能存放一个地址,所以一个指针变量的大小就应该是8个字节

2.指针类型

  变量有许多不同的类型,有整形,浮点数······,那么指针也是有类型的。

例如:

int num=1;

p=&num;

  要将&num(num的地址)保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢?

  我们给指针变量相应的类型。

  char  *p = NULL;

  int   *p = NULL;

  short *p = NULL;

  long  *p = NULL;

  float *p = NULL;

  double *p = NULL;

  这里可以看到,指针的定义方式是: type + *

  其实:

  char* 类型的指针是为了存放 char 类型变量的地址。

  short* 类型的指针是为了存放 short 类型变量的地址。

  int* 类型的指针是为了存放 int 类型变量的地址。

  以此类推。

  那么指针类型存在的意义是什么呢?指针的类型决定了指针向前或者向后走一步有多大(距离)。

  接下来,在4.1指针+-整数我们来感受一下指针类型存在的意义。

3. 指针的解引用

  观察下面两段代码在调试后内存中的n。

​
#include <stdio.h>

int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
*pc = 0;  
return 0;
}

 


#include <stdio.h>

int main()
{
int n = 0x11223344;
int *pi = &n;
*pi = 0;   
}

  对char* 的指针解引用并赋值为0,我们观察n在内存中的变化,此时n=0x11223300。

由此可得char* 的指针解引访问了一个字节。

  而对 int* 的指针的解引用并赋值为0,我们观察n在内存中的变化,此时n=0x00000000。由此可得int* 的指针解引访问了四个字节。

  总结:1.对指针解引用代表指针所指目标,访问几个字节取决于指针的类型

             2.对指针解引用可以看到sizeof(type)个数据

4. 指针运算

  4.1指针+-整数

  上代码!

#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;
}

  n的地址在00E4FE68

  char*类型的指针指向n后+1,地址增加了1(由00E4FE68到00E4FE69);

  int*类型的指针指向n后+1,地址增加了4(由00E4FE68到00E4FE6C);

  由此得出:

  对指针加减1,其实是加减所指向类型的大小,既sizeof(type), 这里的type指的是指针的类型。同理:对指针加减n(n是整数),其实是加减n*sizeof(type)。

  4.2指针+-指针

#include <stdio.h> 
int main()
{
int arr[7] = { 0 };
int* p=&arr[0] ;
int *q = &arr[5];
printf("q-p=%d\n", q - p);
return 0;
}

  运行结果

  总结:指针+-指针 代表两指针之间所经历的元素的个数(元素是由指针类型所决定的)

5. 野指针

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

 5.1 为什么会有野指针

  1.指针未初始化

#include <stdio.h> 
int main() 
{ 
int *p;
return 0; 
} 

  2. 指针越界访问

#include <stdio.h> 
int main() 
{ 
   int arr[10] = {0}; 
   int *p = arr;
 *(p+12) = 10;
return 0; 
} 

  3. 指针指向的空间释放

  5.2 如何规避野指针

   指针要初始化,要小心指针越界,避免返回局部变量的地址,指针使用之前检查有效性,再提出很重要的一点,就是要善于利用assert函数。

  assert函数可对指数做合法性校验,若有野指针,调试时会报错。

  这里提供另一种利用if、规避野指针的方法:

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

6. 指针和数组

  我们一起看下面一段代码

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

  由此可得:数组名表示的是数组首元素的地址。 既然是地址,那么我们就可以把数组名当成地址存放到一个指针中,我们就可以使用指针来访问数组。

  举个例子:

int main() 
{ 
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 
int *p = arr; //指针存放数组首元素的地址 
int sz = sizeof(arr) / sizeof(arr[0]); 
int i = 0; 
for (i = 0; i<sz; i++) 
{ 
printf("%d ", *(p + i)); 
} 
return 0; 
}

7. 二级指针

  刚才我们所谈的都是一级指针,现在我们谈谈二级指针。

  指针变量存放的是变量的地址,二级指针存放的就是一级指针的地址。

  我们来写一段代码看看

#include<stdio.h>
int main()
{
	int num = 1;
	int* p = &num;
	int** q = &p;
	return 0;
}

  7.1二级指针的定义

  二级指针的定义方式是: type(type*) + *

  因为二级及以上的指针指向的都是指针变量,在32位的平台上指针的大小都是4字节。所以,在x32位的平台上,任何二级及以上的指针加减1,都是加减4。。同理在在x64位的平台上,任何二级及以上的指针加减1,都是加减8。

  思考题:

#include<stdio.h>
int main()
{
	int num = 1;
	int* p = &num;
	int** q = &p;
	return 0;
}//依旧是这段代码

  问:q=0的实质

  答:q原来存的是指针p的地址,现在改为0.

  问:*q=0的实质

  答:*q是p;*q=0,将p在内存中的内容修改为0,p现在指向内存地址为0的位置。

  问:**q=0的实质

  答:**q是num。此时将num的内容改为0。

8. 指针数组

  指针数组:顾名思义,就是存放指针的数组。

  数组有整型数组、字符数组;

  指针数组也有:整型指针数组、字符指针数组。

  指针数组是如何定义的呢,我们再来举个例子:

标准规定:

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

与指向第一个元素之前的那个内存位置的指针进行比较。

如果感觉看完这篇文章对您有一点点帮助,那就请留下您的赞

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言 _ 指针(超详解析 3分钟完全掌握 总结性讲解 经典通俗) 的相关文章

  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • Zookeeper的功能以及工作原理

    1 ZooKeeper是什么 ZooKeeper是一个分布式的 开放源码的分布式应用程序协调服务 是Google的Chubby一个开源的实现 它是集群的管理者 监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作 最终 将简单易用
  • 2022年5月30日STM32——存储器 和 I2C读写EEPROM

    此内容仅是为了自己方便回忆 内容来源于野火指南者开发板教程 一 存储器 RAM Random Access Memory 随机存储器 当存储器中的消息被读取或写入时 所需要的时间与这段信息所在的位置无关 RAM分为动态随机存储器DRAM D
  • 再见以前说再见 操作系统复习

    mutex semget IPC PRIVATE 1 0666 IPC CREAT 创建信号量 semctl mutex 0 SETVAL 1 互斥信号量mutex赋初值为1 定义p操作 信号量申请操作 p sem num 0 p sem
  • 如何使用Python的Pyecharts做一个数据可视化的Graph 关系图?

    文章目录 前言 一 Pyecharts是什么 二 Graph关系图是什么 三 使用步骤 1 引入库 2 读入数据 3 人物关系 4 结果 总结 前言 Graph 关系图通常用于分析具有复杂性的数据 例如 如果你想探索不同实体之间的关系 你可
  • C# WinForm 默认最大化

    只需要在窗口的Shown事件处理函数中修改 WindowState即可 this WindowState FormWindowState Maximized
  • 事件绑定器-BP

    蓝图上的事件绑定器 在C 中就是代理 类似于这边绑定炸药包 那边爆炸 这个例子是 绑定人的F键 启动着火特效 书上的这个例子有问题 关卡蓝图上 核心在于startfire 事件 1 一边连接这绑定 一边连接着事件触发后的响应 先看第三人称绑
  • SpringBoot使用AOP

    本文介绍SpringBoot中使用Spring AOP 简介 AOP简介 AOP可能对于广大开发者耳熟能详 它是Aspect Oriented Programming的缩写 翻译成中文就是 面向切面编程 这个可能是面试中经常提到的问题 同时
  • 客服如何使用ChatGPT提高工作效率

    文章目录 ChatGPT简介 ChatGPT在客服中的应用 ChatGPT的优势和挑战 客服人员应该如何应对 1 与ChatGPT保持较高的专业水平 2 与ChatGPT建立良好的合作关系 3 强调人性化的服务 4 不断提升沟通和解决问题的
  • [前端] 编译时报错FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

    参考文献 FATAL ERROR Reached heap limit Allocation failed JavaScript heap out of memory Vue cli3执行serve和build命令时nodejs内存溢出问题
  • 【JAVA多线程11】线程基本方法-线程等待(wait)/线程唤醒(notify)

    1 wait notify notifyAll 方法是Object的本地final方法 无法被重写 2 wait 使当前线程阻塞 前提是 必须先获得锁 一般配合synchronized 关键字使用 即 一般在synchronized 同步代
  • Django 快速搭建博客 第四节(hello world视图)

    上一节我们学会了怎样建数据库表 学习数据库的操作 如果想要把它们显示在网页上 我们还得练习一下如何在网页上显示第一个自己写的hello world 视图 1 我们需要在blog下建一个urls py的文件 里面写上 blog urls py
  • react与vue区别及react面试题

    react和vue的区别如下 1 React与Vue最大的区别是模板的编写 Vue鼓励去写近似常规HTML的模板 写起来很接近标准HTML元素 只是多了一些属性 这些属性也可以被使用在单文件组件中 尽管它需要在在构建时将组件转换为合法的Ja
  • springboot优雅实现工厂模式,策略模式——利用spring自动注入list,map性质

    工厂模式 工厂模式 Factory Pattern 是 Java 中最常用的设计模式之一 这种类型的设计模式属于创建型模式 它提供了一种创建对象的最佳方式 在工厂模式中 我们在创建对象时不会对客户端暴露创建逻辑 并且是通过使用一个共同的接口
  • 【WEB】HTTP返回头分析

    Http协议通讯时 在客户端发送请求后 request 服务器端返回的状态码解释 response Http状态码 1 请求收到 继续处理 2 操作成功收到 分析 接受 200 3 完成此请求必须进一步处理 301 302 304 4 请求
  • QObject::connect: Cannot connect QTimer::timeout() to (null)::fuction()

    这几天连接一对信号与槽怎么也连接不上 后来在下面的这个网站找到了答案 https stackoverflow com questions 6238486 qt qobjectconnect cannot connect null 问题在于c
  • [CocoaPods]podspec文件中的resource和resource_bundle

    相信基本上所有的iOS开发同学针对于CocoaPods都不陌生 即便没有用过 也是久闻大名如雷贯耳 作为Objective C和Swift中非常流行的依赖管理工具 它拥有超过10000个公有程序库 通过一份Podfile文件和pod ins
  • Linux集群常用脚本(个人总结)

    声明 1 本文为我的个人复习总结 并非那种从零基础开始普及知识 内容详细全面 言辞官方的文章 2 由于是个人总结 所以用最精简的话语来写文章 3 若有错误不当之处 请指出 常用脚本编写汇总 自定义脚本放在 bin下 并把这个目录配到PATH
  • js生成随机字符串

    function randomString len len len 32 var str ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678 默认去掉了容易混淆的字符oOLl 9gq Vv Uu
  • 2023-9-8 求组合数(一)

    题目链接 求组合数 I include
  • C语言 _ 指针(超详解析 3分钟完全掌握 总结性讲解 经典通俗)

    目 录 1 指针 指针变量及指针的大小 2 指针类型 3 指针的解引用 4 指针运算 4 1指针 整数 4 2指针 指针 5 野指针 5 1 为什么会有野指针 5 2 如何规避野指针 6 指针和数组 7 二级指针 7 1二级指针的定义 8