C语言基础知识:C语言中的指针

news2024/11/24 7:06:54

目录

1、为什么需要指针?

2、指针是什么?

3、指针与变量的关系

4、指针的分类

5、指针的用法

6、指针的运算

7、野指针

8、指针使用时的注意事项


同C语言中其他变量一样,把指针也可以看成是一种变量。不过,这种变量专门存储地址值。

1、为什么需要指针?

指针解决了一些编程中基本的问题。

第一,指针的使用使得不同区域的代码可以轻易的共享内存数据。当然你也可以通过数据的复制达到相同的效果,但是这样往往效率不太好,因为诸如结构体等大型数据,占用的字节数多,复制很消耗性能。但使用指针就可以很好的避免这个问题,因为任何类型的指针占用的字节数都是一样的(根据平台不同,有4字节或者8字节或者其他可能)。

第二,指针使得一些复杂的链接性的数据结构的构建成为可能,比如链表,链式二叉树等等。

第三,有些操作必须使用指针。如操作申请的堆内存。还有:C语言中的一切函数调用中,值传递都是“按值传递”的,如果我们要在函数中修改被传递过来的对象,就必须通过这个对象的指针来完成。

2、指针是什么?

指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量。
在这里插入图片描述
由于内存中的每一个字节都有一个唯一的编号,因此,在程序中使用的变量,常量,甚至数函数等数据,当他们被载入到内存中后,都有自己唯一的一个编号,这个编号就是这个数据的地址。指针就是这样形成的。

char ch = 'a';
int  num = 97;

我们可以大致画出变量ch和num在内存模型中的存储。(假设 char占1个字节,int占4字节)
在这里插入图片描述

3、指针与变量的关系

用来保存 指针 的变量,就是指针变量。如果指针变量p1保存了变量 num的地址,则就说:p1指向了变量num,也可以说p1指向了num所在的内存块 ,这种指向关系,在图中一般用 箭头表示。
在这里插入图片描述

int main(void)
{
    int num = 97;
    int *p1  = #
    char* p2 = (char*)(&num);
    printf("%d\n",*p1);    //输出  97
    putchar(*p2);          //输出  a
    return 0;
}

指针的值:很好理解,如上面的num 变量 ,其地址的值就是0028FF40 ,因此 p1的值就是0028FF40。数据的地址用于在内存中定位和标识这个数据,因为任何2个内存不重叠的不同数据的地址都是不同的。

指针的类型:指针的类型决定了这个指针指向的内存的字节数并如何解释这些字节信息。一般指针变量的类型要和它指向的数据的类型匹配。

由于num的地址是0028FF40,因此p1 和 p2的值都是0028FF40

*p1 : 将从地址0028FF40 开始解析,因为p1是int类型指针,int占4字节,因此向后连续取4个字节,并将这4个字节的二进制数据解析为一个整数 97。

*p2 : 将从地址0028FF40 开始解析,因为p2是char类型指针,char占1字节,因此向后连续取1个字节,并将这1个字节的二进制数据解析为一个字符,即’a’。

同样的地址,因为指针的类型不同,对它指向的内存的解释就不同,得到的就是不同的数据。

4、指针的分类

指针大致可以分为两类:

1、普通指针:指向普通变量的指针,如指向int类型变量的指针。

int *p;

 

2、函数指针:指向函数的指针,可以用来调用该函数。函数指针的定义方式如下:

返回类型 (*指针变量名)(参数列表)

例如,定义一个指向返回值为int类型,参数为两个int类型变量的函数的指针可以如下:

int (*p)(int, int);

5、指针的用法

指针可以用来访问和修改其他变量的值。例如,定义一个指向int类型变量的指针,可以通过以下方式访问和修改该变量的值:

int a = 10;
int *p = &a; 
// 将指针p指向变量a的地址
*p = 20; 
// 修改变量a的值为20
printf("%d\n", a); 
// 输出20

指针还可以用来实现动态内存分配,即在程序运行过程中根据需要分配和释放内存空间。

在C语言中,我们可以使用指针来动态地分配和释放内存。动态内存分配可以在程序运行时根据需要分配内存,而不是在编译时分配固定大小的内存。

动态内存分配的函数有两个:malloc和calloc。它们都使用一个无符号整数(size_t)的参数来指定需要分配的字节数。如果分配成功,这些函数将返回一个指向新分配内存的指针。如果分配失败,它们将返回一个空指针(NULL)。

malloc函数在堆上分配指定数量的字节,但不会初始化内存。calloc函数在堆上分配指定数量的字节,并将内存初始化为0。

例如,以下代码分配了一个大小为10的整型数组,并将其初始化为0:

int *p = calloc(10, sizeof(int));

为了释放动态分配的内存,我们使用free函数。它需要一个指向需要释放的内存块的指针作为参数。注意,只有通过malloc或calloc函数分配的内存才能使用free函数释放。使用未分配的或已经释放的内存块的指针作为参数会导致未定义的行为。

例如,以下代码释放了先前分配的内存:

free(p);

需要注意的是,动态内存分配很容易出错,因此我们应该在使用完分配的内存后立即释放它,以避免内存泄漏或其他问题。建议使用动态内存分配时,要小心谨慎,确保没有内存泄漏和越界访问等问题。

6、指针的运算

指针是一个存储变量内存地址的变量。在C语言中,指针运算包括以下几种类型:

  1. 指针加法:指针可以加上一个整数值,这个整数值会被乘以指针指向类型的大小,然后加到指针的地址上。例如:ptr + n,其中ptr是一个指向类型为int的指针,n是一个整数值。

  2. 指针减法:指针也可以减去一个整数值,这个整数值也会被乘以指针指向类型的大小,然后从指针的地址中减去。例如:ptr - n

  3. 指针比较:指针可以进行比较操作,包括等于、不等于、大于、小于、大于等于、小于等于等。指针之间的比较操作的结果是通常是一个整数值。

  4. 指针赋值:指针还可以进行赋值操作,例如:int *ptr1, *ptr2; ptr1 = ptr2;

需要注意的是,指针运算的结果可能会超出指针指向的内存区域,这会导致程序出现异常行为,如崩溃或数据损坏等。因此,在使用指针时,需要特别注意指针指向的内存区域是否被正确地分配和释放。

7、野指针

在 C 语言中,一个野指针是指一个指针变量,它没有被初始化或指向一个无效的内存地址。野指针可能会导致程序崩溃或产生不可预测的错误行为。

野指针的常见情况包括:

1、没有初始化指针变量

如果一个指针变量没有被初始化,它会指向一个未知的内存地址,这可能会导致程序崩溃或产生不可预测的结果。正确的做法是在使用指针之前,将其初始化为 NULL 或一个有效的内存地址。

2、指向已经被释放的内存

如果一个指针指向了已经被释放的内存,那么在使用这个指针时就会发生访问无效内存的错误。正确的做法是释放内存后,将指针变量设置为 NULL。

3、指向未分配的内存

如果一个指针指向了未分配的内存,那么在使用这个指针时就会发生访问无效内存的错误。正确的做法是在使用指针之前,先分配内存并将指针指向这块内存。

为避免野指针的问题,应该始终将指针初始化为 NULL 或一个有效的内存地址,并在释放内存后将指针设置为 NULL。此外,应该尽可能避免使用野指针,例如在使用指针之前,先检查指针是否为 NULL。

8、指针使用时的注意事项

在C语言中,指针是一种非常重要的数据类型,它可以用来存储内存地址,并且可以通过间接引用符号 "*" 来访问该内存地址中存储的值。在使用指针时需要特别注意以下几点:

  1. 初始化指针:在使用指针之前必须先初始化指针变量,否则会出现未知的结果。初始化指针可以将指针变量初始化为NULL或者是一个有效的内存地址。

  2. 指针的类型:指针变量必须与指向的数据类型匹配。例如,如果指针变量指向一个整型变量,则应该使用 int *p; 而不是 char *p; 。

  3. 指针的地址:指针变量本身也有一个地址,可以通过使用取地址符号 "&" 来获取指针变量的地址。例如, &p 将返回指针变量 p 的地址。

  4. 指针的间接引用:指针变量存储的是内存地址,可以通过间接引用符号 "*" 来访问该内存地址中存储的值。例如, *p 将返回指针变量 p 所指向的内存地址中存储的值。

  5. 指针的运算:指针变量可以进行算术运算,例如加法和减法。这些运算将根据指针所指向的数据类型来调整指针变量的值。

  6. 指针的释放:在使用完指针后,必须释放指针变量所指向的内存空间,否则会出现内存泄漏的问题。可以使用 free() 函数来释放指针变量所指向的内存空间。

总之,使用指针是C语言编程中非常重要的一部分,需要注意以上几点才能正确地使用指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/540404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vscode链接远程服务器开发c++项目

因为要在linux环境下开发c应用,需要一个比较好用的远程工具。之前做深度学习的时候一直用vscode链接服务器写python,感觉用起来很舒服。 vscode下载安装这些就略过了,从插件安装和配置文件开始介绍 参考文章:https://zhuanlan.zh…

如何做一份精致的性能测试报告?

相比于普通的功能测试,性能测试对测试工程师的技能要求更高,一般来说,也只有中高级测试工程师才会有机会做性能测试。 对于题主关心的问题,我拆分出下面三个部分来做解答: 1、性能测试报告的目的 2、性能测试过程中的关…

【算法分析与设计报告】快递终端送货配送系统、基因序列比较、地图染色、文章查重系统、果园篱笆问题(附源码)

一、快递终端送货分配问题 问题描述 假设某快递终端投递站,服务n个小区,小区与快递点之间有道路相连,如下图,边上的权值表示距离。 图1-1 小区快递点图 现在设有m包裹,每个包裹都有自己的目的地及总量。 假设送货员一…

IPB072N15N3G-ASEMI代理英飞凌高压MOS管IPB072N15N3G

编辑:ll IPB072N15N3G-ASEMI代理英飞凌高压MOS管IPB072N15N3G 型号:IPB072N15N3G 品牌:英飞凌 封装:TO-263 最大漏源电流:31A 漏源击穿电压:600V RDS(ON)Max:99mΩ…

第四届“中国法研杯”司法人工智能挑战赛-刑期预测赛道三等奖方案

一、前言 本文将回顾第四届“中国法研杯”司法人工智能挑战赛-刑期预测算法赛道比赛。使用多任务预训练、然后进行微调的形式最终在比赛中取得了三等奖的成绩。 二、任务介绍 主办方在第一届“中国法研杯”比赛上提出了刑期预测任务,本届将针对往届刑期预测准确率…

《终身成长》笔记六——称赞努力的过程,也将其与结果关联

目录 经典摘录 成为好父母好老师 成长型思维模式的真伪 第一种错误理解:很多人将他们身上某些他们喜欢的优点称作“成长型思维模式” 第二种错误理解:很多人认为成长型思维模式只关乎努力,特别是去夸奖别人的努力 第三种错误理解&#xff…

基于树莓派4B的智能家居

基于树莓派4B的智能家居 前言C语言的简单工厂模式工厂模式介绍类和对象工厂模式的优缺点优点缺点 智能家居框架产品工厂卫生间灯设备二楼灯设备餐厅灯设备客厅灯设备泳池灯设备风扇设备锁设备警报器设备地震监测设备火灾监测设备温湿度检测设备 指令工厂语音控制设备server控制…

如何创建样本手册?

第一步:提前研究和规划 首先明确目标客户群体在其中扮演的角色。 谁会穿你的衣服?您品牌的潜在客户是谁?他们的愿望是什么?他们会被什么打动?设置客户角色至关重要,因为它将决定样本手册的基调&#xff0…

Simulink 自动代码生成电机控制:模型仿真速度的优化

目录 方法一 Simulationmode 方法二 多核并行 方法三 Performance Advisor 总结 方法一 Simulationmode 执行下面的指令获取Simulink仿真实时,这里以霍尔FOC的模型为例,在切换模式为Accelerator时不能使用调用子模型的形式,需要把子模型复制…

map的forEach区别

map的forEach区别 先总结下: map和forEach区别是: 1.map有返回值而且必须return返回一个数组才行 ; 而forEach没有返回值可直接打印结果; 即:forEach()方法不会返回执行结果,而是undefined。也就是说,forEa…

vue 在线聊天实战范例(含选择发送表情、图片、视频、音频,自定义右键快捷菜单,一键复制,左右聊天气泡)

最终效果 完整代码 index.vue <template><div class"page"><div class"leftBox"><h1>访客</h1><div class"chatBox"><div class"chatRecordBox"><div v-for"(item, index) in cha…

DBCO-COOH分子量:305.3,CAS:1353016-70-2,二苯基环辛炔-羧基;类似有DBCO-NH2、SH、MAL、NHS等等

中文名称&#xff1a;二苯基环辛炔-羧基 英文名称&#xff1a;DBCO-acid 英文别称&#xff1a;DBCO-COOH cas: 1353016-70-2 分子式&#xff1a;C19H15NO3 分子量&#xff1a;305.3 DBCO-COOH是DBCO 衍生化的常用构件&#xff0c;在EDC、DCC和HATU等活化剂存在下&#xf…

linux kernel menuconfig kconfig makefile

概述 menuconfig是Linux平台用于管理代码工程、模块及功能的实用工具。 menuconfig的使用方式通常是在编译系统之前在系统源代码根目录下执行make menuconfig命令从而打开一个图形化配置界面&#xff0c;再通过对各项的值按需配置从而达到影响系统编译结果的目的。 Nuttx的me…

Spring Boot 数据库操作Druid和HikariDataSource

目录 Spring Boot 数据库操作 应用实例-需求 创建测试数据库和表 进行数据库开发&#xff0c; 在pom.xml 引入data-jdbc starter 参考官方文档 需要在pom.xml 指定导入数据库驱动 在application.yml 配置操作数据源的信息 创建bean\Furn.java 测试结果 整合Druid 到…

六、easyUI中的window(窗口)组件

1.window&#xff08;窗口&#xff09;组件的概述 窗口控件是一个浮动和可拖拽的面板&#xff0c;它可以用作应用程序窗口。默认情况下&#xff0c;窗口可以移动&#xff0c;调整大小和关闭。它的内容也可以被定义为静态HTML或要么通过Ajax动态加载 2.window&#xff08;窗口&…

MySQL-备份+日志:介质故障与数据库恢复

MySQL-备份日志&#xff1a;介质故障与数据库恢复 第1关&#xff1a;备份与恢复任务描述相关知识MySQL的恢复机制MySQL的备份与恢复工具编程要求代码参考 第2关 备份日志&#xff1a;介质故障的发生与数据库的恢复任务描述相关知识编程要求测试说明代码参考 第1关&#xff1a;备…

《分布式微服务电商源码》-项目简介

1.常见的电商模式 市面上有 5 种常见的电商模式 B2B、B2C、C2B、C2C、O2O 1.1.B2B 模式 B2B(Business to Business)&#xff0c;是指商家和商家建立的商业关系&#xff0c;如阿里巴巴. 1.2.B2C 模式 B2C(Business to Consumer) 就是我们经常看到的供应商直接把商品买个用户&a…

057:cesium设置纯颜色材质

第057个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置纯颜色的材质,颜色的表达方式可以参考这篇文章 Cesium七种方法设置颜色 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共87行)相关API参考:专…

用友BIP新零售产品发布,与零售企业共创新未来

随着数智化时代的到来&#xff0c;零售企业不断面临着更多的挑战和机遇。为了满足消费者多元化的需求&#xff0c;零售企业需要采用多种方式来提高竞争力&#xff0c;如多渠道销售、线上线下融合、数智化运营、个性化营销和无缝化体验等。用友BIP新零售为零售企业提供了数智化转…

Jenkins的持续集成与持续部署

系统总体架构 Gitlab Gitlab是一款主要用于代码管理的工具&#xff0c;相较于GitHub&#xff0c;可以自己搭建服务器&#xff0c;这可以避免因为网络速度慢导致部署效率低下&#xff0c;同时&#xff0c;自己搭建服务器&#xff0c;安全性更高。Jenkins Jenkins主要用于管理版本…