C 语言指针完全指南:创建、解除引用、指针与数组关系解析
C 语言中的指针
创建指针
我们可以使用引用运算符 & 获取变量的内存地址:
int myAge = 43; // 一个 int 变量
printf("%d", myAge); // 输出 myAge 的值 (43)
printf("%p", &myAge); // 输出 myAge 的内存地址 (0x7ffe5367e044)
指针是一个将另一个变量的内存地址作为其值的变量。
指针变量指向一个数据类型(如 int)的相同类型,并使用 * 运算符创建。您正在使用的变量的地址被分配给指针:
int myAge = 43; // 一个 int 变量
int* ptr = &myAge; // 一个名为 ptr 的指针变量,存储 myAge 的地址
// 输出 myAge 的值 (43)
printf("%d\n", myAge);
// 输出 myAge 的内存地址 (0x7ffe5367e044)
printf("%p\n", &myAge);
// 使用指针输出 myAge 的内存地址 (0x7ffe5367e044)
printf("%p\n", ptr);
示例解释:
- 创建一个名为
ptr的指针变量,指向一个int变量 (myAge)。请注意,指针的类型必须与您正在使用的变量的类型匹配(本例中为int)。 - 使用
&运算符将myAge变量的内存地址存储并分配给指针。 - 现在,
ptr存储了myAge的内存地址值。
解除引用
在上面的示例中,我们使用指针变量来获取变量的内存地址(与 & 引用运算符一起使用)。
您还可以通过使用 * 运算符(取消引用运算符)获取指针指向的变量的值:
int myAge = 43; // 变量声明
int* ptr = &myAge; // 指针声明
// 引用:使用指针输出 myAge 的内存地址 (0x7ffe5367e044)
printf("%p\n", ptr);
// 解除引用:使用指针输出 myAge 的值 (43)
printf("%d\n", *ptr);
请注意,* 符号在这里可能会让人困惑,因为它在我们的代码中做了两件事:
- 当用于声明 (
int* ptr) 时,它会创建一个指针变量。 - 当不用于声明时,它充当取消引用运算符。
值得注意:在 C 语言中声明指针变量有两种方法:
int* myNum;
int *myNum;
关于指针的注意事项:
- 指针是 C 语言区别于其他编程语言(如 Python 和 Java)的一大特点。
- 它们在 C 语言中很重要,因为它们允许我们操作计算机内存中的数据。这可以减少代码量并提高性能。如果您熟悉像列表、树和图这样的数据结构,您应该知道指针对于实现它们特别有用。有时您甚至必须使用指针,例如在处理文件时。
- 但是要小心; 指针必须谨慎处理,因为有可能损坏存储在其他内存地址的数据。
C 语言中的指针和数组
您也可以使用指针访问数组。
考虑以下整数数组
int myNumbers[4] = {25, 50, 75, 100};
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", myNumbers[i]);
}
结果:
25
50
75
100
让我们尝试打印每个数组元素的内存地址,而不是打印每个数组元素的值:
int myNumbers[4] = {25, 50, 75, 100};
int i;
for (i = 0; i < 4; i++) {
printf("%p\n", &myNumbers[i]);
}
结果:
0x7ffe70f9d8f0
0x7ffe70f9d8f4
0x7ffe70f9d8f8
0x7ffe70f9d8fc
请注意,每个元素的内存地址的最后一位数字都不同,增加了 4。
这是因为 int 类型的大小通常为 4 个字节,请记住:
// 创建一个 int 变量
int myInt;
// 获取一个 int 的内存大小
printf("%lu", sizeof(myInt));
结果:4
因此,从上面的“内存地址示例”中,
您可以看到编译器为每个数组元素预留了 4 个字节的内存,这意味着整个数组占用 16 个字节(4 * 4)的内存存储空间:
int myNumbers[4] = {25, 50, 75, 100};
// 获取 myNumbers 数组的大小
printf("%lu", sizeof(myNumbers));
结果:16
指针与数组的关系
好的,那么指针和数组之间有什么关系呢?好吧,在 C 语言中,数组的名称实际上是指向数组第一个元素的指针。
感到困惑?让我们试着更好地理解这一点,并再次使用上面的“内存地址示例”。
第一个元素的内存地址与数组的名称相同:
int myNumbers[4] = {25, 50, 75, 100};
// 获取 myNumbers 数组的内存地址
printf("%p\n", myNumbers);
// 获取第一个数组元素的内存地址
printf("%p\n", &myNumbers[0]);
结果:
0x7ffe70f9d8f0
0x7ffe70f9d8f0
这基本上意味着我们可以通过指针来操作数组!
怎么操作呢?由于 myNumbers 是指向 myNumbers 中第一个元素的指针,因此您可以使用 * 运算符来访问它:
int myNumbers[4] = {25, 50, 75, 100};
// 获取 myNumbers 中第一个元素的值
printf("%d", *myNumbers);
结果:25
要访问 myNumbers 中的其他元素,您可以增加指针/数组(+1、+2 等):
int myNumbers[4] = {25, 50, 75, 100};
// 获取 myNumbers 中的第二个元素的值
printf("%d\n", *(myNumbers + 1));
// 获取 myNumbers 中的第三个元素的值
printf("%d", *(myNumbers + 2));
// 等等..
结果:
50
75
或者循环遍历它:
int myNumbers[4] = {25, 50, 75, 100};
int *ptr = myNumbers;
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", *(ptr + i));
}
结果:
25
50
75
100
您也可以使用指针更改数组元素的值:
int myNumbers[4] = {25, 50, 75, 100};
// 将第一个元素的值改为 13
*myNumbers = 13;
// 将第二个元素的值改为 17
最后
为了方便其他设备和平台的小伙伴观看往期文章:
微信公众号搜索:Let us Coding,关注后即可获取最新文章推送
看完如果觉得有帮助,欢迎 点赞、收藏、关注
C 语言指针完全指南:创建、解除引用、指针与数组关系解析的更多相关文章
- Perl解除引用:从引用还原到数据对象
使用引用可以指向数据对象,这似乎很简单. @name1=qw(longshuai wugui); @name2=qw(xiaofang tuner); $ref_name=\@name1; push ...
- 【C语言入门教程】4.5 指针变量的定义与引用
指针变量是包含内存地址的变量.一般的变量直接包含一个特定的值,而指针变量包含的是某一特定数据类型的内存地址.普通变量直接引用其中的值,指针变量则间接引用所指向内存地址中的值.指针变量在使用前需要声明与 ...
- C语言学习笔记 (002) - C++中引用和指针的区别(转载)
下面用通俗易懂的话来概述一下: 指针-对于一个类型T,T*就是指向T的指针类型,也即一个T*类型的变量能够保存一个T对象的地址,而类型T是可以加一些限定词的,如const.volatile等等.见下图 ...
- perl5 第十二章 Perl5中的引用/指针
第十二章 Perl5中的引用/指针 by flamephoenix 一.引用简介二.使用引用三.使用反斜线(\)操作符四.引用和数组五.多维数组六.子程序的引用 子程序模板七.数组与子程序八.文件句 ...
- JVM 平台上的各种语言的开发指南
JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...
- C语言学习书籍推荐《C语言接口与实现:创建可重用软件的技术》下载
<C语言接口与实现:创建可重用软件的技术>概念清晰.实例详尽,是一本有关设计.实现和有效使用C语言库函数,掌握创建可重用C语言软件模块技术的参考指南.书中提供了大量实例,重在阐述如何用一种 ...
- Java中“指针”的解释以及对“引用”的理解
Java中"指针"的解释以及对"引用"的理解 初学Java面对对象编程,对于一些概念还真的有点难以理解,主要是因为不由自主的联系到以前学过的C语言知识,时不时的 ...
- Go 语言:如何利用好 TDD 学习指针并了解 Golang 中的 error 处理
我们在上一节中学习了结构体(structs),Go语言:利用 TDD 驱动开发测试 学习结构体.方法和接口 它可以组合与一个概念相关的一系列值. 你有时可能想用结构体来管理状态,通过将方法暴露给用户的 ...
- R 语言编码风格指南
R 语言是一门主要用于统计计算和绘图的高级编程语言.这份 R 语言编码风格指南旨在让我们的 R代码更容易阅读.分享和检查.以下规则系与 Google 的 R 用户群体协同设计而成. 概要: R编码风格 ...
- 来自 Google 的 R 语言编码风格指南
来自 Google 的 R 语言编码风格指南R 语言是一门主要用于统计计算和绘图的高级编程语言. 这份 R 语言编码风格指南旨在让我们的 R 代码更容易阅读.分享和检查. 以下规则系与 Google ...
随机推荐
- Apifox:成熟的测试工具要学会自己写接口文档
好家伙, 在开发过程中,我们总是避免不了进行接口的测试, 而相比手动敲测试代码,使用测试工具进行测试更为便捷,高效 今天发现了一个非常好用的接口测试工具Apifox 相比于Postman,他还拥有一个 ...
- 【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
问题描述 消费型逻辑应用(Consumption Logic App)使用触发器模式消费 Azure Service Bus的消息,当Service Bus中存在大量消息等待消费时,Logic App ...
- 【Azure 应用服务】Function App / App Service 连接 Blob 报错
问题描述 因 Blob 启用了防火墙功能,但是当把App Service 或 Function App的出站IP地址都加入到Blob的白名单中,为什么访问还是403错误呢? 问题解答 Azure St ...
- Spark任务性能调优总结
一.shuffle调优 大多数Spark作业的性能主要就是消耗在了shuffle环节,因为该环节包含了大量的磁盘IO.序列化.网络数据传输等操作.因此,如果要让作业的性能更上一层楼,就有必要对shuf ...
- 【2024面试刷题】一、Spring Cloud 面试题
1.什么是 Spring Cloud? Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如 服务发现注册.配置中心.智能路 ...
- element_ui 知识点整理
第一章复习,树型组件数据填充:数据组件需要的数据绑定到:data 但是具体那些字绑生成标签需要在定义一人:props ="这儿绑定对象" 对象中label children ...
- Zabbix与乐维监控对比分析(三)——对象管理篇
大家好,我是乐乐.今天就不更新zabbix6.0的使用教程了.在前面的文章中,我们详细介绍了Zabbix与乐维监控在架构.性能.Agent管理.自动发现.权限管理等方面的对比分析,本篇是Zabbix对 ...
- base64实现图片多图上传功能
function webPic_upload($savepath,$url_data){$mark=ture; $pic_url=''; if(is_array($url_data)){ foreac ...
- cache 本地&分布式(-redis) & JSON对象转换
本地缓存 最简单的cache, 做一个map就行 private final Map<String,List<User>> cache=new HashMap<>( ...
- linux-关于conio.h文件的文件缺失问题
链接: https://pan.baidu.com/s/1Qzo4CkJB1_5E-3rDLtfG4Q 提取码: fh65 编辑以下这个依赖库就可以了 $ cd libconio-1.0.0 $ ./ ...