重生之我在异世界学编程之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.mzph.cn/web/67901.shtml

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

相关文章

密码学的数学基础1-素数和RSA加密

数学公式推导是密码学的基础, 故开一个新的课题 – 密码学的数学基础系列 素数 / 质数 质数又称素数。 一个大于1的自然数&#xff0c;除了1和它自身外&#xff0c;不能被其他自然数整除的数叫做质数&#xff1b;否则称为合数&#xff08;规定1既不是质数也不是合数&#xff0…

音视频入门基础:RTP专题(7)——RTP协议简介

一、引言 本文对RTP协议进行简介。在简介之前&#xff0c;请各位先下载RTP的官方文档《RFC 3550》和《RFC 3551》。《RFC 3550》总共有89页&#xff0c;《RFC 3551》总共有44页。本文下面所说的“页数”是指在pdf阅读器中显示的页数&#xff1a; 二、RTP协议简介 根据《RFC 35…

半导体器件与物理篇7 微波二极管、量子效应和热电子器件

基本微波技术 微波频率&#xff1a;微波频率涵盖约从0.1GHz到3000GHz&#xff0c;相当于波长从300cm到0.01cm。 分布效应&#xff1a;电子部件在微波频率&#xff0c;与其在较低频率的工作行为不同。 输运线&#xff1a;一个由电阻、电容、电感三种等效基本电路部件所组成的…

【C++】B2122 单词翻转

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 &#x1f4af;一、我的做法代码实现&#xff1a;代码解析思路分析 &#x1f4af;二、老师的第一种做法代码实现&a…

麦芯(MachCore)应用开发教程5 --- 工位和晶圆传输

麦芯是构建在windows系统上的设备应用操作系统&#xff0c;利用该系统可以快速高效的开发一款设备专用软件。希望进一步了解请email: acloud163.com 黄国强 2025/02/03 一、工位与子设备的关系 想象工厂中的流水线工作站&#xff0c;每个工位&#xff08;Station&#xff09…

Python从0到100(八十七):CNN网络详细介绍及WISDM数据集模型仿真

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

C++ Primer 迭代器

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

【C++篇】位图与布隆过滤器

目录 一&#xff0c;位图 1.1&#xff0c;位图的概念 1.2&#xff0c;位图的设计与实现 1.5&#xff0c;位图的应用举例 1.4&#xff0c;位图常用应用场景 二&#xff0c;布隆过滤器 2.1&#xff0c;定义&#xff1a; 2.2&#xff0c;布隆过滤器的实现 2.3&#xff0c; 应…

VR触感数据手套:触感反馈赋予虚拟交互沉浸式体验

随着动作捕捉技术的蓬勃发展&#xff0c;动捕数据手套成为了手部动作捕捉与虚拟交互的便捷工具&#xff0c;为人们打开了通往虚拟世界的新大门。在众多产品中&#xff0c;mHand Pro作为一款多功能兼具的VR动作捕捉数据手套&#xff0c;凭借其卓越的性能&#xff0c;在手部动作捕…

追逐低空经济,无人机研学技术详解

追逐低空经济&#xff0c;无人机研学技术成为了一个备受关注的领域。以下是对无人机研学技术的详细解析&#xff1a; 一、无人机研学技术概述 无人机研学技术是以无人机为核心&#xff0c;结合航空科技、电子技术、机械原理等多领域知识的一种教育实践活动。它旨在通过理论学习…

(done) MIT6.S081 2023 学习笔记 (Day7: LAB6 Multithreading)

网页&#xff1a;https://pdos.csail.mit.edu/6.S081/2023/labs/thread.html (任务1教会了你如何用 C 语言调用汇编&#xff0c;编译后链接即可) 任务1&#xff1a;Uthread: switching between threads (完成) 在这个练习中&#xff0c;你将设计一个用户级线程系统中的上下文切…

Kubernetes学习之通过Service访问Pod

一、基础概述 1.当通过deployment等controller动态创建和销毁pod使得每个pod都有自己的ip地址&#xff0c;当controller用新的pod替代发生故障的pod时&#xff0c;新的pod会分配到新的ip地址&#xff0c;那么客户端如何稳定的找到并访问pod提供的服务。 2.创建service service从…

【优先算法】专题——前缀和

目录 一、【模版】前缀和 参考代码&#xff1a; 二、【模版】 二维前缀和 参考代码&#xff1a; 三、寻找数组的中心下标 参考代码&#xff1a; 四、除自身以外数组的乘积 参考代码&#xff1a; 五、和为K的子数组 参考代码&#xff1a; 六、和可被K整除的子数组 参…

CDDIS从2025年2月开始数据迁移

CDDIS 将从 2025 年 2 月开始将我们的网站从 cddis.nasa.gov 迁移到 earthdata.nasa.gov&#xff0c;并于 2025 年 6 月结束。 期间可能对GAMIT联网数据下载造成影响。

谷歌Titans模型论文解析,Transformer迎来变革拐点——DeepSeek能否“接招”?

一、引入 Titans 模型 我们将深入探讨谷歌研究院的一篇新论文《Titans: Learning to Memorize at Test Time》&#xff0c;该论文介绍了一种名为 Titans 的新模型架构。 Titans 在缓解 Transformer 二次方成本问题的同时&#xff0c;展现出了令人期待的成果。Titans 模型的设…

新春贺岁,共赴AGI之旅

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 往期精彩文章推荐 季姮教授独家文字版干货 | 面向知识渊博的大语言模型 关于AI TIME AI TIME源起于2019年&#xff0c;旨在发扬科学思辨精神&#xff0c;邀请各界人士对人工智能理论、算法和场景应用的本质问题…

Baklib推动数字化内容管理解决方案助力企业数字化转型

内容概要 在当今信息爆炸的时代&#xff0c;数字化内容管理成为企业提升效率和竞争力的关键。企业在面对大量数据时&#xff0c;如何高效地存储、分类与检索信息&#xff0c;直接关系到其经营的成败。数字化内容管理不仅限于简单的文档存储&#xff0c;更是整合了文档、图像、…

【memgpt】letta 课程4:基于latta框架构建MemGpt代理并与之交互

Lab 3: Building Agents with memory 基于latta框架构建MemGpt代理并与之交互理解代理状态,例如作为系统提示符、工具和agent的内存查看和编辑代理存档内存MemGPT 代理是有状态的 agents的设计思路 每个步骤都要定义代理行为 Letta agents persist information over time and…

FPGA|例化生成的PLL功能IP核

1、例化上一篇文章中调用的IP核&#xff0c;新建文件PLL_test.v 2、代码如图 timescale 1ns / 1ps module PLL_test(input clk,input rst_n,output clkout0,output clkout1,output clkout2,output clkout3,output clkout4);wire locked;PLL pll_inst(.inclk0(clk),.c0(clkout0)…

【C++】P5734 【深基6.例6】文字处理软件

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;题目描述输入格式输出格式示例输入与输出输入&#xff1a;输出&#xff1a; &#x1f4af;我的做法操作1&#xff1a;在文档末尾插入字符串操作2&…