当前位置: 首页 > news >正文

C语言中指针的说明

什么是指针?

在C语言当中,我们可以将指针理解为内存当中存储的地址,就像生活当中,一个小区里面,在小区里面有很单元,每一栋单元,单元内的房间有着不同的房间号,我们可以同过几栋几单元去寻找我们想要找到的房间,同样的,我们在C语言当中,指针就是我们寻找想要的房间的一种手段。

指针变量和地址

上面那一段话,已经让我们初步理解了指针

我们可以看一下这一段代码

其中 0x0115F95C   0x0115F95D   0x0115F95E   0x0115F95F这4个字节代表着a=10所代表的地址,并且每一个字节都是代表着地址

下面我们将通过&(取地址操作符来得到a的地址)

这边显示的结果是同上面通过内存调试出来的结果是相同的

这里我们通过&符号将a的地址存储到指针变量p  并且类型为int*的指针

指针变量也是⼀种变量,这种变量就是⽤来存放地址的,存放在指针变量中的值都会理解为地址。

上面那张图我们可以看到  int*p=&a;

那么*p=&a有什么用处呢?

#include<stdio.h>
int main(){int a = 100;int* pa = &a;*pa = 0;return 0;}

上面那一段代码我们通过*pa来改变了a的值,结果如下图

有同学肯定在想,这⾥如果⽬的就是把a改成0的话,写成 a = 0; 不就完了,为啥⾮要使⽤指针呢? 其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径,写代码就会更加灵活, 后期慢慢就能理解了。

指针变量的大小(在VS2022中)

分别为x86以及x64环境下面

我们可以看到指针变量的大小在统一环境下面他们的大小是相同的

结论:

• 32位平台下地址是32个bit位,指针变量⼤⼩是4个字节

• 64位平台下地址是64个bit位,指针变量⼤⼩是8个字节 X64环境输出结果

• 注意指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,⼤⼩都是相同的。

指针变量的意义以及和地址的关系

那么指针变量大小有什么意义呢?

我们看下面两段代码

 //代码1 
#include <stdio.h>int main(){int n = 0x11223344;int *pi = &n; *pi = 0;   return 0;}
 //代码2 
#include <stdio.h>int main(){int n = 0x11223344;char *pc = (char *)&n;*pc = 0;return 0;}

这两个代码的结果是代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。

结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)。 ⽐如: char* 的指针解引⽤就只能访问⼀个字节,⽽ int* 的指针的解引⽤就能访问四个字节。

指针变量的地址变化

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

我们可以看出, char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。

这就是指针变量的类型差异带来的变化。

结论:指针的类型决定了指针向前或者向后走⼀步有多大(距离)。

指针运算 指针的基本运算有三种:

• 指针+-整数

• 指针-指针

• 指针的关系运算

野指针

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

导致野指针的原因:1. 指针未初始化 2. 指针越界访问 3. 指针指向的空间释放

避免野指针的方面:1.指针初始化 2.⼩⼼指针越界 3.指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性 4.避免返回局部变量的地址

assert断言包含在assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为“断⾔”。

assert(p != NULL);

用来 验证变量p是否等于NULL 。如果确实不等于 NULL ,程序继续运⾏,否则就会终⽌运⾏,并且给出报错信息提⽰。

传值调用和传址调用

传值调用

 #include <stdio.h>void Swap1(int x, int y){int tmp = x;x = y;y = tmp;}int main(){int a = 0;int b = 0;scanf("%d %d", &a, &b);Swap1(a, b);printf("交换前: a=%d b=%d\n", a, b);printf(" 交换后:a=%d b=%d\n", a, b);return 0;}

结论:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实 参。 所以Swap1是失败的了。

传址调用

#include<stdio.h>
void Swap2(int*px, int*py){int tmp = 0;tmp = *px;*px = *py;*py = tmp;}
int main{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:a=%d b=%d\n", a, b);Swap2(&a, &b);printf("交换后:a=%d b=%d\n", a, b);return 0;}

 

我们可以看到实现成Swap2的⽅式,顺利完成了任务,这⾥调⽤Swap2函数的时候是将变量的地址传 递给了函数,这种函数调用方式叫:传址调用。

传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所 以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改 主调函数中的变量的值,就需要传址调用。

相关文章:

  • 浏览器打开 three.js-r160/editor/index.html 后,为何显示白屏
  • C++,观察者模式,模拟Qt的信号和槽机制
  • iOS Universal Links 配置
  • 算法家族之一——二分法
  • Blender + Marvelous Designer(MD)服装,Quad Remesher四边面拓扑布线、UV投射
  • 【ARM Cache 系列文章 1.1 -- Cache size 读取详细介绍及代码实现】
  • STM32F103单片机工程移植到航顺单片机HK32F103注意事项
  • Diffusers代码学习: T2I Adapter
  • 在vscode 中使用npm的问题
  • 【Spring Boot】异常处理
  • cad导入su线条不在一个平面怎么办?
  • Java | Leetcode Java题解之第132题分割回文串II
  • 分享一个用python写的本地WIFI密码查看器
  • 【risc-v】arm和riscv有什么关系或者联系?
  • Elasticsearch 管道查询语言 ES|QL 现已正式发布
  • 30秒的PHP代码片段(1)数组 - Array
  • Android Studio:GIT提交项目到远程仓库
  • MaxCompute访问TableStore(OTS) 数据
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • Spark学习笔记之相关记录
  • spring boot 整合mybatis 无法输出sql的问题
  • uni-app项目数字滚动
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 大快搜索数据爬虫技术实例安装教学篇
  • 分布式任务队列Celery
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 推荐一个React的管理后台框架
  • 线性表及其算法(java实现)
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • Spring Batch JSON 支持
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • #Linux(make工具和makefile文件以及makefile语法)
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #职场发展#其他
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • $NOIp2018$劝退记
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (11)MSP430F5529 定时器B
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (zhuan) 一些RL的文献(及笔记)
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (生成器)yield与(迭代器)generator
  • (十)c52学习之旅-定时器实验
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (一)appium-desktop定位元素原理
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .Net 垃圾回收机制原理(二)
  • .NET程序员迈向卓越的必由之路
  • .NET框架
  • .sh 的运行
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)