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

C语言:指针(一)

目录

  • 1.内存和地址
  • 2. 指针变量和地址
    • 2.1 取地址操作符(&)
    • 2.2 指针变量和解引用操作符(*)
      • 2.2.1 指针变量
      • 2.2.2 解引用操作符(*)
    • 2.3 指针变量的大小
  • 3.指针变量的类型和意义
    • 3.1 指针的解引用
    • 3.2 指针+ -指针
    • 3.3 void*指针
  • 4.const修饰指针
    • 4.1 const修饰变量
    • 4.2 const修饰指针变量
  • 5.传值调用和传址调用

1.内存和地址

在生活中,我们住的房子一般都有门牌号,学生一般都有学号,注册一个软件账户一般都有账户编号,可见给一些事物编上号可以方便我们的生活。
计算机也是这样,计算机中处理数据的机器时CPU(中央处理器),它在处理数据的时候是在内存中读取数据,处理后将数据放回内存。在内存中将其划分为一个一个的内存单元,每个内存单元的大小取一个字节(8个bite),每个内存单元也有一个编号,就相当于门牌号一样,这样CPU就可以快速访问内存中需要的数据了。
内存单元就相当一间学生宿舍,一个字节能存放8个比特位,就相当于一间宿舍住了8个人。

1byte= 8bite
1kb = 1024byte
1mb = 1024kb
1Gb = 1024mb
1Tb = 1024Gb
1Pb = 1024Tb

生活中我们也把门牌号叫做地址,在计算机中,我们把内存单元的编号也叫做地址还可叫做指针
所以:内存单元编号 == 地址 == 指针

2. 指针变量和地址

2.1 取地址操作符(&)

取地址操作符&和按位与操作符&是同一种符号,但是功能完全不一样,而且取地址符是单目操作符,按位与操作符是双目操作符。
在C语言中创建变量其实就是向内存申请一块空间,比如

int a = 10;

这段代码就是向内存中申请4个字节(int类型占用4个字节)用于存放整数10,那如何得到这个地址呢,那么就要用到取地址操作符(&),比如:
在这里插入图片描述
这里的地址是用16进制表示
而int类型的数据会占用4个字节的大小,所以**&a取出的是所占4个字节中地址较小的字节的地址。**
在这里插入图片描述
十六进制的a表示的数就是10,当我们知道了第一个字节的地址,就可以往下顺藤摸瓜找到其他的地址

2.2 指针变量和解引用操作符(*)

2.2.1 指针变量

当我们用取地址操作符拿到一个地址后就可以将这个地址存放到指针变量中,比如:

int main() {int a = 10;int* pa = &a;return 0;
}

指针变量是一种变量,这种变量是用来存放地址的,存放在指针变量的值都会被理解为地址
pa是指针变量,int*是指针变量的类型, *表示pa是指针变量,int表示pa指向的类型是int类型。这里的 int和星号中间加不加空格都表示指针变量,没有去区别。

2.2.2 解引用操作符(*)

指针变量用来保存地址,而解引用操作符(*)用来使用地址
在C语言中,我们拿到了指针就可以通过指针找到指针指向的对象,这里就需要*(解引用操作符)

int main() {int a = 10;int* pa = &a;*pa = 0;return 0;

*pa的意思就是通过指针变量pa找到pa指向的对象a,然后改变它的值,上述代码就是将a的值由10改为0.

*pa = 0;的效果和a = 0;的效果一样,都是将a的值置为0,但是使用指针提供了一种新的修改途径。

2.3 指针变量的大小

在32位计算机中有32根地址总线(相关知识可以自行学习),每根地址总线都可以使用电信号来表示0和1,这样就由32根地址总线产生的二进制序列就可以当作地址,那么一个地址就是32个bite位,需要4个字节来存储。
所以:任何指针变量的大小都是4个字节(64位机是8个字节)

int main() {printf("%zd\n", sizeof(char*));printf("%zd\n", sizeof(int*));printf("%zd\n", sizeof(double*));printf("%zd\n", sizeof(short*));printf("%zd\n", sizeof(long int*));return 0;
}

在这里插入图片描述

3.指针变量的类型和意义

既然在相同平台下所有的指针类型的大小都是一样的,那么为什么还要设置这么多的指针变量呢。

3.1 指针的解引用

对比以下代码:

int main() {int a = 0x11223344;int* pa = &a;*pa = 0;return 0;
}
int main() {int a = 0x11223344;char* pa = &a;*pa = 0;return 0;
}

通过调试中的内存监控可知,代码1会将0x11223344中的4个字节全部置为0,而代码2只会将第一个字节44置为0,其他不变。
在这里插入图片描述
结论:指针的类型决定了对指针解引用的时候有多大的权限(一次能操作几个字节)
比如,int类型的指针变量可以解引用4个字节,而char类型的指针变量只能访问1个字节

3.2 指针+ -指针

int main() {int n = 10;int* pi = &n;char* pc = &n;printf("%p\n", &n);printf("%p\n", pi);printf("%p\n", pc);printf("%p\n", pi + 1);printf("%p\n", pc + 1);return 0;
}

运行结果如下:
在这里插入图片描述
这里的pi和pc都指向变量n,而pi+1加了4个字节,因为pi是int*类型的指针变量,而pc+1只加

了1个字节,因为pc是char* 的指针变量。
结论:指针的类型决定了指针想前或者其向后走一步有多少距离。

3.3 void*指针

在指针类型中有一种特殊的指针类型是void*类型,它是无具体类型的指针(泛型指针),它可以用来接收任何类型的地址,但也有局限性:不能进行+和-和解引用的操作

int main() {int a = 0x11223344;void* pa = &a;*pa = 0;//错误操作return 0;
}

void*指针可以接受不同类型的地址,但是无法直接进行指针运算

4.const修饰指针

变量是可以修改的,而在变量前面加上const修饰那么该变量就不能被修改了

4.1 const修饰变量

int main() {const int a = 10;a = 29;return 0;
}

在这里插入图片描述
可以看到,变量a被const修饰过后,那么改值就不能修改了,而这个限制只是在语法层面加上限制,我们可以用指针来越过这个限制,比如:
在这里插入图片描述
上面用指针变量pa来读取a的地址,而用解引用操作符操作指针变量a,使其修改值为20,那么有什么办法能让指针也不能改变其值呢?

4.2 const修饰指针变量

int main() {const int a = 10;const int* pa = &a;*pa = 20;//错误printf("%d\n", a);return 0;
}

在这里插入图片描述
可以看出,在指针变量pa前面加上const,那么该指针变量就无法进行去引用操作并赋值的操作
注意:const int* pa = &a;的效果和 int const * pa = &a;的效果一致

那const放在a的右边呢

int main() {const int a = 10;int* const pa = &a;*pa = 20;printf("%d\n", a);return 0;
}

这样就对pa的值没有限制作用了,加在右边的作用是限制指针变量的内容不能修改。
这里必须要弄懂三个概念的含义:

1.pa存放的是a的地址 2.pa是指针变量,也是一种变量,他有自己的地址 3.*pa是pa指向的空间即a的值

上述代码就是限制了变量pa里面存放的值不能改变

int main() {const int a = 10;int* const pa = &a;*pa = 20;printf("%d\n", a);int b = 0;pa = &b;//错误return 0;
}

在这里插入图片描述
结论:

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

5.传值调用和传址调用

传值调用就是调用函数,参数是值。而传址调用就是传的地址
比如:

用函数实现交换两个数

void Swap(int x, int y) {int type = x;x = y;y = type;
}
int main() {int a = 10;int b = 20;printf("交换前:%d %d\n", a, b);Swap(a, b);printf("交换后:%d %d\n", a, b);return 0;
}


这里可以看到交换值不成功,这是因为实参传递给形参时,形参会单独创建一分临时空间来接受实参,对形参的修改不影响实参
可以使用指针来实现两个数的交换

void Swap(int *x, int *y) {int type = 0;type = *x;*x = *y;*y = type;
}
int main() {int a = 10;int b = 20;printf("交换前:%d %d\n", a, b);Swap(&a, &b);printf("交换后:%d %d\n", a, b);return 0;
}

在这里插入图片描述
传址调用可以让函数和主调函数建立真正的联系,在函数内部可以修改主调函数的变量;所以只是需要主调函数中的值进行计算,那么就可以使用传值调用;如果函数内部要修改主调函数中变量的值,那么就要传址调用。

/考研势在必行/

相关文章:

C语言:指针(一)

目录 1.内存和地址2. 指针变量和地址2.1 取地址操作符(&)2.2 指针变量和解引用操作符(*)2.2.1 指针变量2.2.2 解引用操作符(*) 2.3 指针变量的大小 3.指针变量的类型和意义3.1 指针的解引用3.2 指针 -指…...

【leetcode刷题之路】面试经典150题(3)——哈希表+区间

文章目录 5 哈希表5.1 【哈希表】赎金信5.2 【数学】同构字符串5.3 【数学】单词规律5.4 【哈希表】有效的字母异位词5.5 【哈希表】字母异位词分组5.6 【双指针】两数之和5.7 【数学】快乐数5.8 【哈希表】219. 存在重复元素 II5.9 【数学】最长连续序列 6 区间6.1 【数学】汇…...

群晖NAS DSM7.2.1安装宝塔之后无法登陆账号密码问题解决

宝塔的安装就不在这赘述了,只说下,启动之后默认账号密码无法登陆的问题。 按照上面给出的账号密码,无法登陆 然后点忘记密码,由于是docker安装的,根目录下没有/www/server/panel 。 也没有bt命令 要怎么修改呢。 既然…...

9、使用 ChatGPT 的 GPT 制作自己的 GPT!

使用 ChatGPT 的 GPT 制作自己的 GPT! 想用自己的 GPT 超越 GPT ChatGPT 吗?那么让我们 GPT GPT 吧! 山姆 奥特曼利用这个机会在推特上宣传 GPTs 的同时还猛烈抨击了埃隆的格罗克。 GPTs概览 他们来了! 在上周刚刚宣布之后,OpenAI 现在推出了其雄心勃勃的新 ChatGPT…...

企业微信应用开发:使用Cpolar域名配置进行本地接口回调的调试指南

文章目录 1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 企业微信开发者在应用的开发测试阶段,应用服务通常是部署在开发环境,在有数据回调的开发场…...

js 可选链运算符(?.)空值合并运算符(??)逻辑空赋值运算符(??=)

可选链运算符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 运算符的功能类似于 . 链式运算符,不同之处在于,在引用为空 (nullish ) (null 或者 undefined) 的情况下不会引起…...

vue 手势解锁功能

效果 实现 <script setup lang"ts"> const canvasRef ref<HTMLCanvasElement>() const ctx ref<CanvasRenderingContext2D | null>(null) const width px2px(600) const height px2px(700) const radius ref(px2px(50))const init () > …...

介绍 CI / CD

目录 一、介绍 CI / CD 1、为什么要 CI / CD 方法简介 1、持续集成 2、持续交付 3、持续部署 2、GitLab CI / CD简介 3、GitLab CI / CD 的工作原理 4、基本CI / CD工作流程 5、首次设置 GitLab CI / CD 6、GitLab CI / CD功能集 一、介绍 CI / CD 在本文档中&#x…...

Stable Diffusion 3 Early Preview发布

2月22日&#xff0c;Stability AI 发布了 Stable Diffusion 3 early preview&#xff0c;这是一种开放权重的下一代图像合成模型。据报道&#xff0c;它继承了其前身&#xff0c;生成了详细的多主题图像&#xff0c;并提高了文本生成的质量和准确性。这一简短的公告并未附带公开…...

【解决(几乎)任何机器学习问题】:特征选择

当你创建了成千上万个特征后&#xff0c;就该从中挑选出⼏个了。但是&#xff0c;我们绝不应该创建成百上千个⽆⽤的特征。特征过多会带来⼀个众所周知的问题&#xff0c;即 "维度诅咒"。如果你有很多特征&#xff0c;你也必须有很多训练样本来捕捉所有特征。什么是 …...

24 双非计算机秋招总结

引言 我整理了一份 10w 字数的前端技术文档&#xff08;飞书&#xff09;&#xff0c;地址&#xff1a;https://qx8wba2yxsl.feishu.cn/docx/Vb5Zdq7CGoPAsZxMLztc53E1n0k?fromfrom_copylink&#xff0c;欢迎对前端感兴趣的同学查看、共建、分享。 PS&#xff1a;我是一名大四…...

用友NC65与用友NCC对接集成NC65-凭证列表查询打通凭证新增

用友NC65与用友NCC对接集成NC65-凭证列表查询打通凭证新增 数据源平台:用友NC65 用友NC是为集团与行业企业提供的全线管理软件产品&#xff0c;由亚太本土最大的企业管理软件提供商用友公司研发提供&#xff0c;用友NC率先采用J2EE架构和先进开放的集团级开发平台UAP&#xff0…...

【初中生讲机器学习】12. 似然函数和极大似然估计:原理、应用与代码实现

创建时间&#xff1a;2024-02-23 最后编辑时间&#xff1a;2024-02-24 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…...

【达梦数据库】查看pesg回滚段信息的视图和SQL

一些达梦回滚段是使用情况的查询SQL&#xff0c;供排查“回滚记录版本太旧&#xff0c;无法获取用户记录” 等类似问题时使用 视图名说明主库备库v$pseg_items显示回滚系统中当前回滚项信息&#xff08;回滚线程的工作信息&#xff09;总行数WORKER_THREADS1查询 no rowsv$pseg…...

UML---活动图

活动图概述 活动图&#xff08;Activity Diagram&#xff09;是UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;中的一种行为建模工具&#xff0c;主要用于描述系统或业务流程中的一系列活动或操作。活动图通常用于描述用例中的行为&#xff0c…...

编程笔记 Golang基础 018 常量与变量

编程笔记 Golang基础 018 常量与变量 一、常量常量的定义iota特性 二、变量变量定义变量作用域零值与初始化类型转换注意事项 三、重要性 常量&#xff0c;就是在程序编译阶段就确定下来的值&#xff0c;而程序在运行时则无法改变该值。变量是程序的基本组成单位&#xff0c;用…...

如何使用Douglas-042为威胁搜索和事件应急响应提速

关于Douglas-042 Douglas-042是一款功能强大的PowerShell脚本&#xff0c;该脚本可以提升数据分类的速度&#xff0c;并辅助广大研究人员迅速从取证数据中筛选和提取出关键数据。 该工具能够搜索和识别Windows生态系统中潜在的安全漏洞&#xff0c;Douglas-042会将注意力放在…...

华为配置WLAN AC和AP之间VPN穿越示例

配置WLAN AC和AP之间VPN穿越示例 组网图形 图1 配置WLAN AC和AP之间VPN穿越示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户接入WLAN网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响…...

跨语言的序列化与反序列化

在Java中实现跨语言的序列化与反序列化通常可以采用以下几种方式 使用标准的跨语言序列化格式 可以选择使用一些标准的跨语言序列化格式,例如JSON、XML、Protocol Buffers(ProtoBuf)等。这些格式都是跨语言的,可以方便地在不同的编程语言之间进行数据交换。在Java中,可以…...

软考-中级-系统集成2023年综合知识(三)

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 软考中级专栏回顾 专栏…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践

在电商行业蓬勃发展的当下&#xff0c;多平台运营已成为众多商家的必然选择。然而&#xff0c;不同电商平台在商品数据接口方面存在差异&#xff0c;导致商家在跨平台运营时面临诸多挑战&#xff0c;如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划&#xff0c;涵盖存储系统的布局、数据存储策略等&#xff0c;它明确数据如何存储、管理与访问&#xff0c;为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...

从0开始学习R语言--Day17--Cox回归

Cox回归 在用医疗数据作分析时&#xff0c;最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据&#xff0c;往往会有很多的协变量&#xff0c;即使我们通过计算来减少指标对结果的影响&#xff0c;我们的数据中依然会有很多的协变量&#xff0c;且…...