重生之我在异世界学编程之C语言:深入指针篇(上)

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录

  • 引言
  • 正文
    • (1)内置数据类型指针
      • (2) 自定义类型指针
        • 1.数组指针与指针数组
        • 2. 结构体指针
        • 3.联合体指针
          • (1)联合体指针的定义
          • (2)联合体指针的使用
          • (3)联合体指针的注意事项
      • (3)函数指针
        • 1.函数指针的定义
        • 2.函数指针的赋值
        • 3.函数指针的使用
        • 4.函数指针作为参数
        • 5.函数指针作为返回值
        • 6.函数指针的注意事项
      • (4)空指针(`NULL`)
          • (1)空指针的使用
          • (2)空指针与空字符
          • (3)空指针的注意事项
      • (5)二级指针
        • (1)二级指针的定义
        • (2)二级指针的内存分配
        • (3)二级指针的使用
        • (4)二级指针作为函数参数
        • (5)二级指针的注意事项
      • (6)常量指针与指向常量的指针(const 的用法)
        • 1.指向常量的指针(Pointer to a Constant)
        • 2.常量指针(Constant Pointer)
        • 3.常量指针指向常量(Constant Pointer to a Constant)
        • 4.使用场景和注意事项
  • 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

引言

指针作为C语言语法学习中的一块既极重要又极难懂的知识点,让初学C语言的我们常常苦不堪言。而本文就是为了让像曾经的作者一样的宝子们深刻理解指针这一章节的内容而作,那接下来就跟随作者的视角,一起把各种类型的指针理解透彻!

在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

正文

指针的类型繁复,为了避免出现知识点的遗漏,这里小编采根据指向的内容进行分类,把指针分为了以下6种。让我们一一来学习吧!!


内置类型数据是我们最为常用的数据类型,所以指针的学习我们就从它开始。

(1)内置数据类型指针

顾名思义,这些指针指向内置类型的变量,如整型指针,字符指针等。

详见:

类型内涵及应用
整型指针int*指向整数的指针
浮点型指针float*double*指向浮点数的指针
字符(型)指针char*指向字符的指针,常用于字符串处理
布尔型指针bool*指向布尔值的指针

其次就是自定义类型指针,一起来看看吧!!

(2) 自定义类型指针

自定义类型数据类型有:数组,结构体,枚举,联合体。但是枚举没有对应的枚举指针变量。


这里小编先从数组与指针开始讲起。

1.数组指针与指针数组

数组指针和指针数组是C编程中两个重要的概念,它们虽然名字相似,但含义和用法却有很大的不同。我们先来看看这两个的定义:

  • 数组指针指的是指向数组的指针。它是一个指针,指向一个数组类型的数据。声明一个数组指针时,需要指定数组的元素类型和大小。例如,int (*arrayPtr)[10]表示一个指向包含10个整数的数组的指针。使用数组指针时,可以通过(*arrayPtr)[index]来访问数组中的元素。
  • 指针数组则是指存储指针的数组。它是一个数组,其中的每个元素都是指针。声明指针数组时,需要指定数组的大小和指针指向的类型。例如,int *pointerArray[10]表示一个包含10个指向整数的指针的数组。访问指针数组中的元素,可以直接使用pointerArray[index],然后通过解引用来访问指针指向的数据。

主要区别在于它们的使用场景和内存布局

数组指针通常用于函数参数,以传递多维数组,而指针数组则常用于创建动态的数据结构,如链表和树。

在内存中,数组指针指向的是连续的内存块,而指针数组中的每个指针可以指向任意位置的内存。因此,数组指针在内存访问上更为高效,而指针数组则在数据组织上更为灵活。

  • 总之,理解数组指针和指针数组的区别对于编写高效的C语言程序至关重要。掌握它们各自的特性和适用场景,可以帮助我们更好地设计和实现程序。

2. 结构体指针

定义:结构体指针允许我们通过指针来访问和操作结构体中的数据。结构体是一种复合数据类型,它允许我们将多个不同类型的数据项组合成一个单一的类型。结构体指针则是指向这种复合数据类型的指针。

在C中,结构体指针的声明方式是在结构体类型的前面加上一个星号()。例如,如果有一个名为Person的结构体,声明一个指向该结构体的指针可以写作Person *ptr;。这个指针可以用来指向一个Person类型的结构体实例。

我们以一个代码为例:

#include<stdio.h>
struct book {char name[20];char author[20];int prince;
};
void print(struct book* p) {printf("%s %s %d\n", (*p).name, (*p).author, (*p).prince);printf("%s %s %d\n", p->name, p->author, p->prince);    //“->”操作符可用在:结构体指针指向我们想要访问的结构体中的元素;
}int main() {struct book b1 = {"C语言", "张三", 10};printf("%s %s %d\n", b1.name, b1.author, b1.prince);     //“.”操作符可用在:找到我们想要访问的结构体的元素。print(&b1);return 0;
}

这里的struct book* p就是一个结构体指针变量

主要优点:是它们提供了一种通过内存地址间接访问和修改结构体成员的方法。这在处理大型数据结构时尤其有用,因为它们可以减少内存复制,提高程序的效率。

使用结构体指针时,我们可以通过箭头操作符(->)来访问结构体的成员。例如,如果Person结构体有一个名为name的成员,我们可以通过ptr->name来访问或修改它。

结构体指针也常用于动态内存分配。使用new关键字可以动态创建结构体实例,并返回指向该实例的指针。例如,Person *ptr = new Person;会创建一个新的Person结构体,并使ptr指向它。当不再需要这个结构体时,应该使用delete来释放内存,避免内存泄漏。

结构体指针还可以作为函数参数,允许函数直接修改传入的结构体实例。这在设计模块化和可重用代码时非常有用,因为它允许函数与调用者共享数据,而无需复制整个结构体。

  • 总之,结构体指针提供了一种高效、灵活的方式来访问和操作结构体数据,是编写高效、模块化代码的关键。理解结构体指针的工作原理和正确使用它们,对于任何C/C++程序员来说都是一项基本技能。

3.联合体指针

联合体(Union)指针是指向联合体类型的指针。联合体是一种特殊的数据结构,允许在相同的内存位置存储不同的数据类型。这使得联合体成为一种节省空间的数据类型,因为联合体的大小等于其最大成员的大小,而不是所有成员的总和。

(1)联合体指针的定义

在C/C++中,联合体指针的声明方式是在联合体类型的前面加上一个星号()。例如,如果有一个名为Data的联合体,声明一个指向该联合体的指针可以写作Data *ptr;。这个指针可以用来指向一个Data类型的联合体实例。

(2)联合体指针的使用

使用联合体指针时,我们可以通过箭头操作符(->)来访问联合体的成员。例如,如果Data联合体有一个名为num的成员,我们可以通过ptr->num来访问或修改它。

联合体指针的使用特点:

  • 内存共享:联合体指针允许我们通过指针访问联合体成员,这些成员共享相同的内存位置。这意味着对一个成员的修改会影响其他成员。
  • 类型安全:尽管联合体可以存储不同类型的数据,但使用联合体指针时,编译器会根据联合体的声明来检查成员访问的类型安全。
  • 动态内存分配:与结构体类似,联合体指针也常用于动态内存分配。使用new关键字可以动态创建联合体实例,并返回指向该实例的指针。
  • 灵活性:联合体指针提供了一种灵活的方式来处理不同类型的数据,尤其是在需要节省空间或者需要通过同一个内存位置存储不同类型数据的场景中。
(3)联合体指针的注意事项
  • 初始化:在使用联合体指针之前,应该确保指针已经被正确初始化,指向一个有效的联合体实例。
  • 内存释放:如果使用new动态分配了联合体实例,那么在不再需要时,应该使用delete来释放内存,避免内存泄漏。
  • 成员访问:在使用联合体指针访问成员时,必须确保访问的是当前存储在联合体中的成员类型,否则可能会导致未定义行为。
  • 联合体指针提供了一种节省空间且灵活的方式来处理不同类型的数据。

(3)函数指针

函数指针是C语言中一个强大的特性,它允许将函数的地址赋给一个变量,使得可以通过这个变量来调用函数。这种机制提供了一种灵活的方式来处理函数,使得函数可以像数据一样被传递和操作。

1.函数指针的定义

函数指针的声明需要指定函数的返回类型、指针类型(即*),以及函数的参数列表。例如,如果有一个返回int类型、接受两个int参数的函数add,那么对应的函数指针声明如下:int (*funcPtr)(int, int);

这里,funcPtr是一个指向函数的指针,它可以存储add函数的地址。

2.函数指针的赋值

要将函数的地址赋给函数指针,可以直接使用函数名。

这是因为:在C语言中,函数名本身就是一个指向函数的指针,因此可以直接赋值给函数指针。

3.函数指针的使用

使用函数指针调用函数时,需要使用括号来包围函数指针和参数。

例如,int result = funcPtr(5, 3); // 调用add函数

4.函数指针作为参数

函数指针常用作其他函数的参数,这使得函数可以接收另一个函数作为输入,从而提供高度的灵活性。例如,可以定义一个接受函数指针作为参数的函数:

void applyFunction(int x, int y, int (*func)(int, int)) {int result = func(x, y);// 处理结果
}

在这个例子中,applyFunction接受两个int参数和一个函数指针参数,然后调用这个函数指针指向的函数。

5.函数指针作为返回值

函数指针也可以作为函数的返回值,这允许函数返回一个函数。这种技术可以用来实现回调函数和策略模式。

小编已经在之前的函数篇提及。

6.函数指针的注意事项
  • 类型匹配:函数指针必须指向与声明匹配的函数类型,否则会导致编译错误或运行时错误。
  • 空函数指针:函数指针可以被初始化为NULL,表示它不指向任何函数。
  • 内存管理:如果函数指针用于动态分配的函数对象,需要确保正确管理内存,避免内存泄漏。

在C语言中,空指针(Null Pointer)是一个特殊的指针值,它不指向任何有效的对象或函数。空指针的主要作用是表示“没有指向任何东西”或“没有有效的地址”。在C语言中,空指针常被用来表示一个指针变量尚未被分配具体的内存地址,或者用来表示某个指针变量不再指向任何对象。

(4)空指针(NULL

定义:在C语言中,空指针被定义为NULL,它是一个宏,在标准库<stddef.h>中定义。NULL的具体值是0,这意味着在大多数平台上,空指针和数值0是等价的。然而,NULL的使用更加明确,因为它专门用来表示空指针,而0可能在其他上下文中有其他含义。

(1)空指针的使用

空指针通常用于以下几种情况:

  • 初始化指针:在声明指针变量时,如果没有立即分配内存,可以将指针初始化为NULL,以表明该指针当前不指向任何对象。

函数返回值:当一个函数需要返回一个指针,但没有有效的对象可以返回时,可以返回NULL

  • 检查指针有效性:在使用指针之前,检查它是否为NULL是一个好习惯,这可以防止解引用空指针导致的程序崩溃。
(2)空指针与空字符

需要注意的是:空指针(NULL)和空字符('\0')是两个完全不同的概念。空指针是一个指针值,表示没有指向任何对象,而空字符是一个字符值,通常用来表示字符串的结束。

(3)空指针的注意事项
  • 空指针赋值:不要将NULL赋值给非指针类型的变量,这会导致编译错误。
  • 平台依赖性:虽然在大多数平台上NULL被定义为0,但在某些系统上,NULL可能有不同的定义。因此,最好始终使用NULL而不是直接使用0
  • 空指针与空数组:不要将空指针与空数组混淆。空数组是指一个长度为零的数组,而空指针是一个不指向任何对象的指针。

结论:

  • 空指针可以帮助程序员处理指针变量的未初始化状态和错误情况。

(5)二级指针

在C语言中,二级指针(Double Pointer)是指指向指针的指针它是一个指针变量,存储的值是另一个指针变量的地址。二级指针在处理动态内存分配、多维数组、函数参数传递等方面非常有用。理解二级指针对于深入掌握C语言的指针操作至关重要。

(1)二级指针的定义

二级指针的声明涉及到两个星号()。例如,int **ptr;声明了一个指向int类型指针的指针。这里,ptr是一个二级指针,它可以存储一个int*类型的地址。

(2)二级指针的内存分配

二级指针常用于动态分配多维数组。例如,创建一个二维数组可以通过分配一个指针数组(一级指针),然后为每个指针分配一个一维数组(二级指针)。

(3)二级指针的使用

使用二级指针时,可以通过连续的解引用来访问最终指向的数据。例如,*arr会得到一个int*类型的指针,而**arr会得到一个int类型的值。

(4)二级指针作为函数参数

二级指针也常用于函数参数,特别是需要修改指针指向的值或者需要传递多维数组时。

(5)二级指针的注意事项
  • 初始化:在使用二级指针之前,应该确保它们已经被正确初始化,指向有效的内存地址。
  • 内存释放:如果使用malloccalloc分配了内存,应该在不再需要时使用free来释放内存,避免内存泄漏。
  • 解引用:在使用二级指针时,必须确保已经正确解引用,否则可能会导致访问无效内存,引起程序崩溃。

在C语言中,常量指针和指向常量的指针是两个不同的概念,它们在声明和使用上有所区别,但都与指针和常量的关系有关。

(6)常量指针与指向常量的指针(const 的用法)

1.指向常量的指针(Pointer to a Constant)

指向常量的指针是指指针本身可以被修改,但其指向的数据(常量)不能被修改。这种指针的声明方式是在指针的声明中,将const关键字放在指针的后面,紧挨着指针的类型前面。例如:const int *ptr;

这里,ptr是一个指向int类型的常量的指针。这意味着你可以通过ptr来改变它所指向的地址,但是不能通过ptr来改变所指向地址处的值。

2.常量指针(Constant Pointer)

常量指针是指指针本身的值不能被修改,即一旦指针被初始化后,就不能指向另一个地址。这种指针的声明方式是将const关键字放在指针的声明中,紧挨着指针变量的前面。例如:int value = 10; int *const ptr = &value;

这里,ptr是一个常量指针,它被初始化为指向value的地址,之后你不能再让ptr指向另一个地址,但可以通过ptr来修改value的值。

3.常量指针指向常量(Constant Pointer to a Constant)

这种指针既不能改变指向的地址,也不能通过这个指针来改变指向地址处的值。声明时,const关键字同时放在指针类型和指针变量之间,以及指针类型和指针指向的类型之间。例如:const int *const ptr = &value;

在这个例子中,ptr是一个常量指针,指向一个int类型的常量。这意味着ptr的值(即它所指向的地址)不能被改变,同时ptr所指向的数据也不能被修改。

4.使用场景和注意事项
  • 指向常量的指针:当你需要一个指针来读取但不能修改某些数据时使用,例如,函数参数中传递的只读数据。
  • 常量指针:当你需要一个指针的地址固定不变时使用,例如,指向全局变量或静态变量的指针。
  • 常量指针指向常量:当你需要一个既不能改变指向地址,也不能通过指针改变数据的指针时使用,例如,防止函数内部修改传入的参数。
  • 常量指针与指向常量的指针提供了不同的保护级别,帮助程序员控制数据的访问和修改。

快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP 配置与应用(不同网段)

想做一个自己学习的有关的csdn账号&#xff0c;努力奋斗......会更新我计算机网络实验课程的所有内容&#xff0c;还有其他的学习知识^_^&#xff0c;为自己巩固一下所学知识&#xff0c;下次更新校园网设计。 我是一个萌新小白&#xff0c;有误地方请大家指正&#xff0c;谢谢…

YOLOv5训练自己的数据及rknn部署

YOLOv5训练自己的数据及rknn部署 一、下载源码二、准备自己的数据集2.1 标注图像2.2 数据集结构 三、配置YOLOv5训练3.1 修改配置文件3.2 模型选择 四、训练五、测试六、部署6.1 pt转onnx6.2 onnx转rknn 七、常见错误7.1 训练过程中的错误7.1.1 cuda: out of memory7.1.2 train…

STM32 ST7735 128*160

ST7735 接口和 STM32 SPI 引脚连接 ST7735 引脚功能描述STM32 引脚连接&#xff08;示例&#xff0c;使用 SPI1&#xff09;SCLSPI 时钟信号 (SCK)PA0(SPI1_SCK)SDASPI 数据信号 (MOSI)PA1 (SPI1_MOSI)RST复位信号 (Reset)PA2(GPIO 手动控制)DC数据/命令选择 (D/C)PA3 (GPIO 手…

使用Redis缓解数据库压力+三种常见问题

目录 一.如何使用 Redis 缓存减缓数据库的压力 &#xff1a; 二.Redis缓存穿透&#xff1a; 布隆过滤器的工作原理&#xff1a; 三.缓存雪崩&#xff1a; 缓存雪崩的处理策略&#xff1a; 四.缓存击穿&#xff1a; 使用 Redis 缓存来减缓数据库的压力是一个常见的优化手段…

移动端VR处理器和传统显卡的不同

骁龙 XR 系列芯片 更多地依赖 AI 技术 来优化渲染过程&#xff0c;而传统的 GPU 渲染 则倾向于在低画质下运行以减少负载。这种设计是为了在有限的硬件资源下&#xff08;如移动端 XR 设备&#xff09;实现高性能和低功耗的平衡。以下是具体的分析&#xff1a; 1. AI 驱动的渲染…

AI新玩法:Flux.1图像生成结合内网穿透远程生图的解决方案

文章目录 前言1. 本地部署ComfyUI2. 下载 Flux.1 模型3. 下载CLIP模型4. 下载 VAE 模型5. 演示文生图6. 公网使用 Flux.1 大模型6.1 创建远程连接公网地址 7. 固定远程访问公网地址 前言 在这个AI技术日新月异的时代&#xff0c;图像生成模型已经成为了创意工作者和开发者手中…

WordPress果果对象存储插件

将网站上的图片等静态资源文件上传至七牛云对象存储&#xff0c;可以减轻服务器文件存储压力&#xff0c;提升静态文件访问速度&#xff0c;从而加速网站访问速度。 支持&#xff1a;阿里云对象存储、华为云对象存储、百度云对象存储、腾讯云对象存储、七牛云对象存储。 下载…

2025美赛倒计时,数学建模五类模型40+常用算法及算法手册汇总

数学建模美赛倒计时&#xff0c;对于第一次参加竞赛且没有相关基础知识的同学来讲&#xff0c;掌握数学建模常用经典的模型算法知识&#xff0c;并熟练使用相关软件进行建模是关键。本文将介绍一些常用的模型算法&#xff0c;以及软件操作教程。 数学建模常用模型包括&#xf…

Maven的下载安装配置

maven的下载安装配置 maven是什么 Maven 是一个用于 Java 平台的 自动化构建工具&#xff0c;由 Apache 组织提供。它不仅可以用作包管理&#xff0c;还支持项目的开发、打包、测试及部署等一系列行为 Maven的核心功能 项目构建生命周期管理&#xff1a;Maven定义了项目构建…

2000-2010年各省第三产业就业人数数据

2000-2010年各省第三产业就业人数数据 1、时间&#xff1a;2000-2010年 2、来源&#xff1a;统计年鉴、各省年鉴 3、指标&#xff1a;行政区划代码、地区、年份、第三产业就业人员数&#xff08;万人&#xff09; 4、范围&#xff1a;31省 5、指标解释&#xff1a;第三产业…

【系统环境丢失恢复】如何恢复和重建 Ubuntu 中的 .bashrc 文件

r如果你遇到这种情况&#xff0c;说明系统环境的.bashrc 文件丢失恢复&#xff1a; 要恢复 ~/.bashrc 文件&#xff0c;可以按照以下几种方式操作&#xff1a; 恢复默认的 ~/.bashrc 文件 如果 ~/.bashrc 文件被删除或修改&#xff0c;你可以恢复到默认的版本。可以参考以下…

Docker网段和服务器ip冲突导致无法访问网络的解决方法

若宿主机所在网络的网段为172.[17-31].xx.xx&#xff0c;则会与Docker本身内部网络间出现冲突&#xff0c;此时需要重新配置Docker默认地址池 一&#xff1a;查看docker的默认网段 route 二&#xff1a;修改docker的默认网段 etc/docker/daemon.json文件增加修改网段信息 {…

2.2.1 语句结构

ST&#xff08;Structured Text&#xff09;语言是一种基于IEC 61131-3标准的高级文本编程语言&#xff0c;其语法规则严格且清晰。以下是ST语言中关于分号、注释和代码块的详细语法规则说明&#xff1a; 分号&#xff08;;&#xff09; 作用&#xff1a;分号用于表示语句的结…

音频入门(二):音频数据增强

本文介绍了一些常见的音频数据增强方法&#xff0c;并给出了代码实现。 目录 一、简介 二、代码 1. 安装必要的库 2. 代码 3. 各函数的介绍 4. 使用方法 参考&#xff1a; 一、简介 音频数据增强是机器学习和深度学习领域中用于改善模型性能和泛化能力的技术。 使用数据…

网络(一)

目录 1. 网络基础(一); 2. 网络套接字; 3. TCP实现; 1. 网络基础(一) 1.1 网络发展: 从一个个计算器都是独立的, 到计算机连接起来进行数据共享, 后期计算机数量很多通过交换器和路由器进行传输(局域网). 广域网就是世界各个计算器进行数据共享, 也是由一个个局域网组成. 1…

风光并网对电网电能质量影响的matlab/simulink仿真建模

这个课题早在一几年的时候比较热门&#xff0c;之前作电科院配电网的一个项目中也有所涉及&#xff0c;我把其中一部分经典仿真模型思路分享给大家&#xff0c;电能质量影响这部分&#xff0c;我在模型中主要体现的就是不同容量的光伏、风电接入&#xff0c;对并网点的电压影响…

【深度学习入门】深度学习知识点总结

一、卷积 &#xff08;1&#xff09;什么是卷积 定义&#xff1a;特征图的局部与卷积核做内积的操作。 作用&#xff1a;① 广泛应用于图像处理领域。卷积操作可以提取图片中的特征&#xff0c;低层的卷积层提取局部特征&#xff0c;如&#xff1a;边缘、线条、角。 ② 高层…

MySQL(4)多表查询

引言&#xff1a;为什么需要多表的查询&#xff1f; A&#xff1a;提高效率&#xff0c;多线进行。 高内聚、低耦合。 一、多表查询的条件 1、错误的多表查询&#xff1a; SELECT employee_id,department_name FROM employees,departments; SELECT employee_id,department…

PIC单片机HEX文件格式分析

在调试PIC单片机在bootloader程序时&#xff0c;需要将hex文件转换为bin文件&#xff0c;在转换之前先了解一下hex文件中数据是如何定义的。 直接打开一个LED灯闪烁的程序生成的hex文件&#xff0c;芯片型号为PIC18F46K80 可以看到每条数据都是由6部分组成的&#xff0c;下面分…

CANoe Trace窗口

文章目录 一、Trace窗口简介二、Trace窗口打开三、Trace窗口菜单栏介绍1. Detail View2. Statistic View3. Difference view4. Predefined filter5. Analysis filter6. Toggle time mode7. Toggle display mode8. Change font size 四、Trabe窗口配置1. 打开 Trace配置窗口2. 增…