指针进阶篇(1)

news/2024/10/21 20:37:12/

目录

🤔 前言🤔

一、😊字符指针😊

二、😜指针数组😜

三、😝数组指针😝

3.1数组指针的定义

3.2&数组名VS数组名

3.3数组指针的使用

 四、🌝数组参数,指针参数🌝

4.1一维数组传参

4.2二维数组传参

4.3一级指针传参

4.4二级指针传参

🍀小结🍀


🎉博客主页:小智_x0___0x_

🎉欢迎关注:👍点赞🙌收藏✍️留言

🎉系列专栏:C语言进阶篇

🎉代码仓库:Xiaozhi_c

  

        家银们更新不易,你们的👍点赞👍和👉关注👈真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!

        关注我,关注我,关注我,让你们看到更多的优质内容!!


🤔 前言🤔

我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:
1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。
4. 指针的运算。
这个章节,我们继续探讨指针的高级主题>


一、😊字符指针😊

在指针类型中我们知道有一种指针类型为字符指针char*。

一般使用:

int main()
{char ch = 'w';char* pc = &ch;*pc = 'w';return 0;}

还有一种使用方式如下:

int main()
{const char* pstr = "hello world.";//这里是把一个字符串的首字符地址存放在了pstr指针变量中。printf("%s", pstr);return 0;
}

运行结果>

 代码const char* pstr = "hello world.";

特别容易让我们以为是把字符串hello world存放到字符指针pstr里了,但本质上是把字符串hello world.首字符的地址放到了pstr中。

上面代码的意思是把一个常量字符串的首字符 h 的地址存放到指针变量 pstr 中。

我们来看一道面试题>

#include <stdio.h>
int main()
{char str1[] = "hello world.";char str2[] = "hello world.";const char* str3 = "hello world.";const char* str4 = "hello world.";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}

直接看结果>

画图解释>

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。


二、😜指针数组😜

在《初阶指针》章节我们也学了指针数组,指针数组是一个存放指针的数组。
这里我们再复习一下,下面指针数组是什么意思?
 

int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组

三、😝数组指针😝

3.1数组指针的定义

数组指针是指针?还是数组?

答案是:指针。

我们已经熟悉:

整型指针:int * pint;能够指向整型数据的指针。

浮点型指针:float * pf,能够指向浮点型数据的指针。

那数组指针应该是:能够指向数组的指针。

我们来看看下面这些代码那个是数组指针?

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?

解释>

int (*p)[10];

p先和*结合,说明p是一个指针变量,然后指向的是一个大小为10个整型的数组,所以p是一个指针,指向一个数组,叫数组指针。

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

3.2&数组名VS数组名

对于下面数组:
 

int arr[10];

arr和&arr分别是啥?

我们知道arr是数组名,数组名表示数组的首元素地址。

那么&arr数组名又是个啥?

我们来看一段代码:
 

#include<stdio.h>
int main()
{int arr[10]={0};printf("%p\n",arr);printf("%p\n",&arr);return 0;
}

运行结果> 

 两个结果相同可见数组名和&数组名打印的地址是一样的。

难道就没有什么区别了吗?

我们再来看一段代码:

#inlcude<stdio.h>
int main()
{int arr[10] = { 0 };printf("arr = %p\n", arr);printf("&arr= %p\n", &arr);printf("arr+1 = %p\n", arr + 1);printf("&arr+1= %p\n", &arr + 1);return 0;
}

运行结果>

 根据上面代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。

实际上:&arr表示的是数组的地址,而不是数组书元素的地址

本例中的&arr类型是:int(*)[10],是一种数组指针类型,而数组指针+1,跳过整个数组的大小,所以&arr+1相对于&arr的差值是40。

3.3数组指针的使用

数组指针怎么使用呢?

既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。

看代码>

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
void print_arr2(int(*arr)[5], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
int main()
{int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };print_arr1(arr, 3, 5);//数组名arr,表示首元素的地址//但是二维数组的首元素是二维数组的第一行//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址//可以数组指针来接收print_arr2(arr, 3, 5);return 0;
}

学习了指针数组和数组指针,我们一起来看看下面代码都是什么意思>

int arr[10];
int *parr1[10];
int(*parr2)[10];
int(*parr3[10])[5];

 四、🌝数组参数,指针参数🌝

在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?

4.1一维数组传参

#include <stdio.h>
void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int* arr)//ok
{}
void test2(int* arr[20])//ok
{}
void test2(int* arr[])//ok
{}
void test2(int** arr)//ok
{}
int main()
{int arr[10] = { 0 };int* arr2[20] = { 0 };test(arr);test2(arr2);
}

4.2二维数组传参

void test(int arr[3][5])//ok?
{}
void test(int arr[][])//err
{}
void test(int arr[][5])//ok?
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int* arr)//err
{}
void test(int* arr[5])//err
{}
void test(int(*arr)[5])//ok
{}
void test(int** arr)//err
{}
int main()
{int arr[3][5] = { 0 };test(arr);
}

4.3一级指针传参

#include <stdio.h>
void print(int *p, int sz)
{
int i = 0;
for(i=0; i<sz; i++)
{
printf("%d\n", *(p+i));
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
//一级指针p,传给函数
print(p, sz);
return 0;
}

那么当一个函数的参数部分为一级指针的时候,函数能接受什么参数?

void test1(int *p)
{}
//test1函数能接收什么参数?

函数传递参数可以是>

int main()
{int a = 10;int* p = &a;int arr[10];test1(arr);test1(&a);test1(p);return 0;
}

4.4二级指针传参

#include <stdio.h>
void test(int** ptr)
{printf("num = %d\n", **ptr);
}
int main()
{int n = 10;int* p = &n;int** pp = &p;test(pp);test(&p);return 0;
}

那当函数参数为二级指针的时候,可以接收什么参数?

void test(char** p)
{}
int main()
{char c = 'b';char* pc = &c;char** ppc = &pc;char* arr[10];test(&pc);test(ppc);test(arr);return 0;
}

🍀小结🍀

今天我们学习了字符指针、指针数组、数组指针、数组参数、指针参数,相信大家看完有一定的收获。

种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~,本文中也有不足之处,欢迎各位随时私信点评指正!
本节课的代码已上传gitee仓库


http://www.ppmy.cn/news/10291.html

相关文章

基础算法(二)——归并排序

归并排序 介绍 归并排序是一种复杂度O(nlog(n)nlog(n)nlog(n))的排序算法&#xff0c;并且在任何情况下都是&#xff0c;但是它不是原地算法&#xff0c;即需要额外存储空间 其原理是&#xff0c;先将区间均匀分成左右两半&#xff0c;然后再对左右两半继续二分&#xff0c;…

LeetCode 138. 复制带随机指针的链表(C++)

思路&#xff1a; 用哈希表实现&#xff0c;创建一个哈希表来对应原链表中的每一个节点&#xff0c;这样也可以将原链表中的所有结点的next和random关系映射到哈希表复制链表中。 原题链接&#xff1a;https://leetcode.cn/problems/copy-list-with-random-pointer/description…

2023年1月7日:fastadmin导出数据为excel格式

需求图&#xff1a; 实现方法&#xff1a; 第一种方法&#xff1a;fastadmin自带导出数据&#xff0c;直接点击下载即可 效果图第二种方法&#xff1a;自定义导出按钮&#xff0c;需要编写方法 效果图&#xff1a; 效果图代码实现 首先&#xff1a;前端按钮代码(可直接拿来用…

Apifox调用Security权限接口

Apifox调用Security权限接口1. SpringBoot3.0集成SpringSecurity1.1 pom1.2 properties配置2. Apifox 配置2.1 配置根目录Auth2.2 ApiFox 分享调用本地接口本教程环境&#xff1a; Apifox&#xff1a;2.2.14 &#xff08;建议更新到最新版本&#xff0c;老版本Auth从父级继承可…

2023春招面试专题:高并发解决方案

如何理解高并发&#xff1f; 高并发意味着大流量&#xff0c;需要运用技术手段抵抗流量的冲击&#xff0c;这些手段好比操作流量&#xff0c;能让流量更平稳地被系统所处理&#xff0c;带给用户更好的体验。 我们常见的高并发场景有&#xff1a;淘宝的双11、春运时的抢票、微…

组合数素数判定++和* *t=*afor循环你真的门儿清吗救济金发放

目录 P63_习题4-1_组合数 为什么m n-m P64_习题4-3_素数判定 为什么要floor 到底为什么判断到sqrt(n)即可 和* *t*a for循环你真的门儿清吗 为什么要把较大的数组放在main函数外 P82_eg4-3_救济金发放_UVa133 P63_习题4-1_组合数 防止溢出&#xff0c;又因为m < n…

leetcode 1658. 将 x 减到 0 的最小操作数

给你一个整数数组 nums 和一个整数 x 。每一次操作时&#xff0c;你应当移除数组 nums 最左边或最右边的元素&#xff0c;然后从 x 中减去该元素的值。请注意&#xff0c;需要 修改 数组以供接下来的操作使用。 如果可以将 x 恰好 减到 0 &#xff0c;返回 最小操作数 &#x…

字节跳动青训营笔试题解

文章目录前言一、单选题二、多选题三、编程题T1.旋转数组最大值题目思路代码T2.社交圈题目思路代码四、简答题题目思路前言 第五届字节跳动青训营-后端专场笔试题解&#xff0c;简单做了一下&#xff0c;选择题和简答题不知道是否正确&#xff0c;编程题是通过了的&#xff0c…