C语言进阶第二篇【指针进阶】(上)

简介: C语言进阶第二篇【指针进阶】(上)

前言:Hello!我是@每天都要敲代码。今天就让我们一起学习一下指针的进阶,指针可算是C语言中的重中之重,我们一定要学好指针这一课;这里我也会尽可能详细的说明每个知识点。


引言:

我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:

1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。

2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。

3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。

4. 指针的运算。

这个章节,我们继续探讨指针的高级主题。


1.字符指针 char*

1.1 常见的两种使用方式

3710d42b5bed4d05bf3f01f8553efc08.png

我们来一起解析一下常量字符串:代码 const char* ps = "hello bit."



f177385d6bfb4c30a475e4767bb23434.png

我们这样看可能会觉得把字符串 hello bit. 放到字符指针 ps 里了;实际上并不是,我们通过调试的过程发现:ps的地址是和h的地址是一样的!


03f45344816b4d7d8500870bec4a34c1.png


所以不要被误导以为是把字符串 hello bit. 放到字符指针 ps 里了;本质是把字符串 hello bit. 首字符(h)的地址放到了ps中。


1.2 经典面试题

b28b62eb8d394d13aee98c60287680b2.png


这里最终输出的是:

3008f8fd807349099042b5a9fdd0e828.png

为什么是这个结果呢?


1、这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。


2、但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。


3、所以str1和str2不同,str3和str4不同。


通过调试进行验证:

dc22fb13b7c9400198959ecb4df72ef7.png



2. 指针数组    int* arr[10]

有了前面的学习,我们都已知晓:


整型数组 int arr[5];存放整型的数组,数组里的每个元素都是int类型 。


字符数组 char arr[5];存放字符的数组,数组里的每个元素都是char类型 。


指针数组 int* arr[10];存放指针的数组,数组里的每个元素都是int*类型。


指针数组是一个存放指针(地址)的数组,本质上还是数组。例如:int* arr[3];数组有3个元素,每个元素是int*(整型指针)类型。既然本质上还是数组,那如何在数组中应用呢?


2.1 一维数组中的应用:

实际上在移位数组的应用并没有什么应用场景,这里只做了解就可以;下面直接上代码:

cf65d3480b47471688c08255ee7b61b0.png



2.2 二维数组中的应用::

在一维数组中,我们是把一个元素取地址作为指针数组里的元素;现在我们不妨把一个数组(数组名就是首元素地址)作为指针数组里面的元素。

bfbb26e5f8ee4cccac822f82ffa12b8d.png



怎么理解呢?我们不妨先画图理解一下:

5eaafdf90f004ea08f1c951ca4c58d39.png


下面看具体代码:

de157610bbcf4cc8ba7f07ee937f89ed.png



其实三种打印方式本质是相同的:我们都知道*(arr+i)就等价与ar[i];所以arr[i][j]===>


*( arr[i] + j) ===> *( *(arr+i) + j)


3. 数组指针  int (*p)[10]

3.1 数组指针的定义

我们已经熟悉:

整形指针: int * p; 指向整形数据的指针。


浮点型指针: char * p; 指向浮点型数据的指针。


数组指针:int (*p) [10];本质是一种指针;指向数组的指针,int(*)[10]就是它的类型。


要注意:[ ]的优先级要高于*号的,所以必须加上()来保证p先和*结合


a0261e00f87c427e9d6da05b9537d315.png


我们不妨在举一个例子来练手,如果是double* d[5],写成数组指针的形式是怎样的呢?照葫芦画瓢: double* (*pd)[5] = &d


3.2 &数组名 VS 数组名

第一种情况:

7c4eee1e040b483bb0b02e9a6aa10252.png


   arr是数组名代表的是首元素的地址,&arr代表的是整个数组的地址;我们惊奇的发现它们的地址居然是一样的。为什么呢?&arr我们取出的是数组的地址,那数组的地址不也有起始地址?所以这两个位置是同一个位置!值一样,但是类型意义不同。比如:char c = 'a',ASCII码值是97;int i = 97,它们的值都是97,但是意义完全不同!


第二种情况:


e4425ed7c9d54aa9998c00a27de0c9b5.png

第2种情况实际是和前面一样的,只不过这次我们把arr和&arr交给了指针来处理;我们最终打印的结果也是相同的 。


第三种情况:

从前面两种情况,我们是看不出arr和&arr有什么本质的区别的,它们的地址相同;那么我们把指针+1又有什么样的结果呢?


93d049c6e90d4ca081e02c3bf6036f3d.png


我们可以得到:p1指针是整型指针,p1+1跳过4个字节;p2是数组指针,p2+1应该跳过一整个数组40(是28这是16进制,十进制就是40);这就体现出它两的区别了!


复习:


数组名是数组首元素的地址,但是有两个例外:


1.sizeof(数组名) ----数组名表示整个数组,计算的是整个数组的大小,单位是字节


2. &数组名----数组名表示整个数组,取出的是整个数组的地址


3.3 数组指针的使用

3.3.1 在一维数组的使用

很别扭,我们一般很少这样写代码:

d81b48669da842d19d25dcb8fe002629.png



3.3.2 在二维数组的使用

二维数组的数组名表示首元素的地址;二维数组首元素是:第一行



532d1e08e88b46ec8768aeecafe40aa0.png


a172c866196e41faab2228b7c432b18a.png

数组指针相当于我们在打印二维数组时,又多了一种方法!


区分:


int arr[5];整型数组


int* arr[5] ;整型指针的数组===》指针数组


int (*parr)[10];数组指针,该指针能够指向一个数组,数组10个元素,每个元素的类型是int


拓展:int (*parr[10])[5];数组指针的数组,该数组能够存放10个数组指针,每个数组指针能够指向一个数组,数组5个元素,每个元素是int类型


4. 数组参数、指针参数

我们在设计函数时,参数既可以写成数组,也可以写成指针!!!


4.1 一维数组传参

4.1.1 常见普通数组传参

 4fc038991145450fb04c4fd4853e5a6b.png


    前面我们都已经学习过了,我们接收参数的时候,既可以写成数组的形式,也可以写成指针的形式;本质上都是把数组首元素的地址传过去!


4.1.2 指针数组传参

08177dd8331d4d83aa2aab4fe3fa76df.png


arr2是一个指针数组:存放int*的数组;


1、前两种,本来是指针数组的形式,我们就以指针数组的形式接收,当然没问题;


2、那如何利用指针接收呢?这个数组有20个元素,每个元素对应的是int*;数组名表示首元素的地址,就是int*的地址!一级指针的地址我们用二级指针接收当然也没问题。

相关文章
|
2月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
62 0
|
25天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
78 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
25天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
49 9
|
25天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
42 7
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
126 13
|
28天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
29天前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
103 3
|
29天前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
1月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
58 11
|
29天前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
39 1