C语言之指针详解(8)

news/2024/5/20 1:54:50/文章来源:https://blog.csdn.net/fjj2397194209/article/details/131253158
目录
本章重点
1. 字符指针
2. 数组指针
3. 指针数组
4. 数组传参和指针传参
5. 函数指针
6. 函数指针数组
7. 指向函数指针数组的指针
8. 回调函数
9. 指针和数组面试题的解析
指针和数组笔试题解析
#include<stdio.h>
int main()
{//一维数组int a[] = { 1,2,3,4 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(a + 0));printf("%d\n", sizeof(*a));printf("%d\n", sizeof(a + 1));printf("%d\n", sizeof(a[1]));printf("%d\n", sizeof(&a));printf("%d\n", sizeof(*&a));printf("%d\n", sizeof(&a + 1));printf("%d\n", sizeof(&a[0]));printf("%d\n", sizeof(&a[0] + 1));return 0;
}
大家可以试着先分析一下结果是多少,分析错了不要紧,我逐个逐个给大家解释
首先这是一个数组,里面放的都是整型数据
数组元素的总大小是16个字节
sizeof(数组名)--数组名表示整个数组
&数组名---数组名表示整个数组
对于第一个sizeof(数组名),计算的是数组的总大小--单位是字节---16
对于第二个sizeof(a+0)结果是4,数组名在这里表示数组首元素的地址,a+0还是首元素的地址,地址的大小就是4/8个字节
对于第三个sizeof(*a)---数组名表示首元素的地址,*a就是首元素,sizeof(*a)就是4
对于第四个sizeof(a+1)--数组名在这里表示首元素的地址,a+1是第二个元素的地址,地址的大小就是4/8个字节
对于第五个sizeof(a【1】)--第二个元素的大小--4
对于第六个sizeof(&a)--&a取出的是数组的地址,但是数组的地址那也是地址,地址的大小就是4/8个字节
对于第七个sizeof(*&a)--16---&a数组的地址,数组的地址解引用访问的数组,sizeof计算的就是数组的大小--单位是字节
对于第八个sizeof(&a+1)--&a是数组的地址,&a+1虽然地址跳过整个数组,但还是地址,所以是4/8个字节
对于第九个sizeof(&a【0】)--&a【0】是第一个元素的地址
对于最后一个sizeof(&a【0】+1)--&a【0】+1是第二个元素的地址
我们把代码结果运行给大家看一下
X86平台演示的结果
X64平台演示的结果

 

下面我们来看字符数组
#include<stdio.h>
int main()
{//字符数组char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr + 0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr + 1));printf("%d\n", sizeof(&arr[0] + 1));return 0;
}
我们还是一个一个来分析
对于第一个sizeof(arr)--计算的是数组的大小,6*1=6个字节
对于第二个sizeof(arr+0)--arr是首元素的地址,arr+0还是首元素的地址,地址的大小是4/8个字节
对于第三个sizeof(*arr)--arr是首元素的地址,*arr就是首元素,首元素是字符大小是一个字节
对于第四个sizeof(arr【1】)--1
对于第五个sizeof(&arr)--&arr虽然是数组的地址,但还是地址,地址大小为4/8个字节
对于第六个sizeof(&arr+1)--&arr+1是跳过整个数组后的地址,地址的大小是4/8个字节
对于最后一个sizeof(&arr【0】+1)--第二个元素的地址---4/8个字节
希望大家能够理解,我们把两个代码运行起来给大家看一下
X86平台演示的结果
X64平台演示的结果

 

我们再来看一组代码

#include<stdio.h>
int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));printf("%d\n", strlen(arr + 0));printf("%d\n", strlen(*arr));printf("%d\n", strlen(&arr));printf("%d\n", strlen(arr[1]));printf("%d\n", strlen(&arr + 1));printf("%d\n", strlen(&arr[0] + 1));return 0;
}

我们还是给大家讲解一下

对于第一个strlen(求字符串长度)---找不到\0的位置,\0的位置不确定,所以结果打印随机值

对于第二个strlen---1--数组名---首元素的地址,和第一种情况相同---随机值

对于第三个strlen---这里传了个'a'--97过去,他就把97当作一个地址,大家有听说过吗?所以这叫非法访问,是有问题的

对于第四个strlen---同第三个,非法访问,是有问题的

对于第五个strlen----取地址arr---虽然是取出来的是数组的地址,但是数组的地址也是从'a'开始的,所以结果也是随机值

对于第六个strlen---也是随机值,但是随机值跟前面的随机值差6

对于第六个strlen---也是随机值,但是比前面的随机值差1

我们还是把代码运行起来给大家看一下

X86平台演示的结果X64平台演示的结果我们接着来看代码

#include<stdio.h>
int main()
{char arr[] = "abcdef";printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr + 0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr + 1));printf("%d\n", sizeof(&arr[0] + 1));return 0;
}

我们还是来给大家讲解一下

第一个:计算的是数组的大小,单位是字节---7

第二个:计算的是地址的大小,arr+0是首元素的地址

第三个:*arr是首元素,计算的是首元素的大小--1

第四个:arr【1】是第二个元素,计算的是第二个元素的大小

第五个:&arr虽然是数组的地址,但也是地址,所以是4/8个字节

第六个:&arr+1是跳过整个数组后的地址,但也是地址---4/8个字节

第七个:&arr【0】+1是第二个元素的地址--4/8个字节

我们来把代码演示结果给大家展示一下

X86平台演示的结果X64平台演示的结果

我们来看下面的代码

#include<stdio.h>
int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));printf("%d\n", strlen(arr + 0));printf("%d\n", strlen(*arr));printf("%d\n", strlen(arr[1]));printf("%d\n", strlen(&arr));printf("%d\n", strlen(&arr + 1));printf("%d\n", strlen(&arr[0] + 1));return 0;
}

还是给大家一个一个讲解一下

第一个:6,字符串的长度

第二个:6,和第一个相同

第三个:非法访问内存,访问97的这个地址,所以是有问题的

第四个:和第三个是一个道理,访问的是'b'--98的地址,属于非法访问,是有问题的

第五个:&arr---数组的地址--strlen的返回类型为const char*,我们正常使用应该使用数组指针---char(*p)7==&arr

第六个:&arr+1把\0也跳过去了,你也不知道后面的字符串有多长,所以结果是随机值

第七个:跳过了a这个字符从b开始往后数,所以长度为5

我们运行代码看一下结果

X86平台演示的结果 X64平台演示的结果

如果大家能够理解,我们继续来看下面的代码

#include<stdio.h>
int main()
{char* p = "abcdef";printf("%d\n", sizeof(p));printf("%d\n", sizeof(p + 1));printf("%d\n", sizeof(*p));printf("%d\n", sizeof(p[0]));printf("%d\n", sizeof(&p));printf("%d\n", sizeof(&p + 1));printf("%d\n", sizeof(&p[0] + 1));return 0;
}

我们还是来解释一下

第一个:计算指针变量p的大小---4/8个字节

第二个:p+1得到的是字符b的地址,地址的大小为4/8个字节

第三个:*p就是字符串的第一个字符,也就是字符a,a为字符--1个字节

第四个:---可以等价等int arr[10]----arr[0]==*(arr+0)    p[0]==*(p+0)=='a',所以还是字符a--大小为1个字节

第五个:计算的地址,地址是4/8个字节

第六个:也是地址,大小为4/8个字节

第七个:b的地址---大小为4/8个字节

我们运行起来看一下效果

X86平台演示的结果

X64平台演示的结果

我们再来看下一个代码

#include<stdio.h>
int main()
{char* p = "abcdef";printf("%d\n", strlen(p));printf("%d\n", strlen(p + 1));printf("%d\n", strlen(*p));printf("%d\n", strlen(p[0]));printf("%d\n", strlen(&p));printf("%d\n", strlen(&p + 1));printf("%d\n", strlen(&p[0] + 1));return 0;
}

第一个:6-从a开始的字符串的长度到\0结束

第二个:5-从b开始的字符串的长度到\0结束

第三个:error--将a的值传过去了

第四个:error--同第三个代码

第五个:地址如果内存分配不同,结果也会不同(涉及大小端知识)--随机值

第六个:也是随机值---取地址加1对于后面的内存,地址的大小我们也不知道,所以是随机值

第七个:5--从第二个元素开始到\0结束

给大家运行代码看一下结果

X86平台演示的结果 

X64平台演示的结果

我们来看最后一个代码

#include<stdio.h>
int main()
{//二维数组int a[3][4] = { 0 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(a[0][0]));printf("%d\n", sizeof(a[0]));printf("%d\n", sizeof(a[0] + 1));printf("%d\n", sizeof(*(a[0] + 1)));printf("%d\n", sizeof(a + 1));printf("%d\n", sizeof(*(a + 1)));printf("%d\n", sizeof(&a[0] + 1));printf("%d\n", sizeof(*(&a[0] + 1)));printf("%d\n", sizeof(*a));printf("%d\n", sizeof(a[3]));return 0;
}

我们还是来给大家分析一下

第一个:48

第二个:4

第三个:16--a【0】相当于第一行作为一维数组的数组名,这里计算的是一行的大小

第四个:4---a【0】是第一行的数组名,数组名此时是首元素的地址,a【0】其实是第一行第一个元素的地址,a【0】+1就是第一行第二个元素的地址,地址大小为4/8个字节

第五个:4--*(a【0】+1)是第一行第二个元素,大小是4个字节

第六个:4--a是二维数组的数组名,所以a是首元素的地址,二维数组的首元素是他的第一行,a就是第一行(首元素)的地址,a+1就是第二行的地址

第七个:16---计算的是第二行的大小,单位是字节

第八个:第二行的地址--4

第九个:计算的是第二行的大小,单位是字节

第十个:a是首元素的地址--第一行的地址,*a就是第一行,计算的是第一行的大小

第十一个:16
给大家把代码运行起来看结果

X86平台演示的结果 

X64平台上演示的结果

指针详解的全部知识就给大家讲完了,希望大家能够有所收获

全章终!!!

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

相关文章

flv 报错 Unsupported codec in video frame: 12

视频播放器播放 flv 报错 [TransmuxingController] > DemuxException: type CodecUnsupported, info Flv: Unsupported codec in video frame: 12 原因 主要是因为我们的播放器不支持 H.265 视频编码&#xff1b; 解决办法 方法一&#xff1a;将设备端的视频编码改为 …

瑞萨RA系列mcu学习笔记--RTT-pwm驱动

方案1&#xff1a;Studio 2.2.6和使用了RASC3.5下使用pwm驱动 开发环境必须说一下&#xff0c;本人在在开发环境的问题上栽了一个跟头&#xff0c; 使用最新版的RTT Studio 2.2.6和使用了RASC4.0的版本生成的公共编译ok&#xff0c;但是一下载到mcu就直接不能运行&#xff1a…

记录一下RocketMQ中遇见的 连环大坑!!!差点没把我摔死

目录 环境&#xff1a;Win10 &#xff0c; 不是 linux 首先我遇见的第一个问题是&#xff1a; No route info of this topic 问题原因&#xff1a; PS&#xff1a; 64位系统环境下&#xff0c;如果软件在安装时安装路径默认c:\progarmfiles即为64位&#xff0c;默认c:\pr…

【备战秋招】每日一题:5月13日美团春招第三题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检&#xff0c;为了更好的阅读体检&#xff0c;&#xff0c;可以查看我的算法学习博客第三题-火车调度 在线评测链接:P1288 题目描述 塔子哥是一位火车车厢调度员。 这一天&#xff0c;一列带有 n 个编号车厢的列车进站了&#xff0c;编号为 1\rightarrow …

kafka 报错 - Cannot assign requested address

背景 在华为云服务器上跑了 zookeeper 和 kafka 的 broker&#xff0c;想内外网分流&#xff0c;重点就是做不到从外网去消费&#xff0c;比如用自己的 windows 笔记本去消费。 配置 server.properties 的 listener 为 broker 所在机子的的内网 IP 后&#xff0c;终于能 star…

ECC算法学习(一)算法公式

ECC 一、ECC简介优缺点运用 二、算法理论基础1. 椭圆曲线的加法2. 椭圆曲线的二倍运算3. 同余运算4. 有限域5. 乘法逆元 三、算法公式1、有限域的负元2、有限域的加法&#xff0c; P Q P Q PQ3. 斜率计算&#xff08;PQ即要计算P点切线&#xff0c;需要求导&#xff09;4. 椭…

【位图布隆过滤器海量数据面试题】

文章目录 1 位图2 布隆过滤器 1 位图 首先我们来看看一个腾讯的面试题&#xff1a;给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。 分析&#xff1a; 40亿个不重复整形数据&#xff0c;大概有160亿字节…

Axios和Spring MVC[前端和后端的请求和响应处理]

在前后端交互中&#xff0c;Axios和Spring MVC扮演着不同的角色&#xff0c;分别负责前端和后端的请求和响应处理。它们之间的作用如下&#xff1a; Axios&#xff08;前端&#xff09;&#xff1a; 发送HTTP请求&#xff1a;前端使用Axios库发送HTTP请求到后端。可以使用Axi…

机器学习实践(1.1)XGBoost分类任务

前言 XGBoost属于Boosting集成学习模型&#xff0c;由华盛顿大学陈天齐博士提出&#xff0c;因在机器学习挑战赛中大放异彩而被业界所熟知。相比越来越流行的深度神经网络&#xff0c;XGBoost能更好的处理表格数据&#xff0c;并具有更强的可解释性&#xff0c;还具有易于调参…

hard fault on thread: mqtt0解决办法

rt thread版本4.1.0 使用paho mqtt软件包 运行一段时间后出现 psr: 0x21000000 r00: 0x5036fc8f r01: 0x5036fc88 r02: 0x00000000 r03: 0x5036fc8f r04: 0x00000007 r05: 0x00000063 r06: 0x00005f70 r07: 0x2001f1d8 r08: 0xdeadbeef r09: 0xdeadbeef r10: 0xdeadbeef r11…

关于Java SSM框架的面试题

一、Spring面试题 1、Spring 在ssm中起什么作用&#xff1f; Spring&#xff1a;轻量级框架作用&#xff1a;Bean工厂&#xff0c;用来管理Bean的生命周期和框架集成。两大核心&#xff1a;1、IOC/DI(控制反转/依赖注入) &#xff1a;把dao依赖注入到service层&#xff0c;se…

28.vite

目录 1 一些概念 1.1 单页面应用程序SPA 1.2 vite 2 初始化vite项目 3 项目中的文件 1 一些概念 1.1 单页面应用程序SPA 单页面应用程序是只有一个页面的前端&#xff0c;切换页面通过前端路由来切换 特点如下 实现了前后端分离&#xff0c;后端仅出接口&#…

动态规划III (买股票-121、122、123、188、309)

CP121 买股票的最佳时机 题目描述&#xff1a; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利…

YOLOv5-7.0添加解耦头

Decoupled Head Decoupled Head是由YOLOX提出的用来替代YOLO Head&#xff0c;可以用来提升目标检测的精度。那么为什么解耦头可以提升检测效果呢&#xff1f; 在阅读YOLOX论文时&#xff0c;找到了两篇引用的论文&#xff0c;并加以阅读。 第一篇文献是Song等人在CVPR2020发表…

【59天|503.下一个更大元素II ● 42. 接雨水】

503.下一个更大元素II class Solution { public:vector<int> nextGreaterElements(vector<int>& nums) {stack<int> st;int n nums.size();vector<int> res (n, -1);for(int i0; i<2*n;i){while(!st.empty()&&nums[i%n]>nums[st.t…

随机的乐趣和游戏

1、猜数字游戏 #GuessingGame.py import random the_number random.randint(1, 10) print("计算机已经在1到10之间随机生成了一个数字&#xff0c;") guess int(input("请你猜猜是哪一个数字: ")) while guess ! the_number:if guess > the_number:p…

PHP设计模式21-工厂模式的讲解及应用

文章目录 前言基础知识简单工厂模式工厂方法模式抽象工厂模式 详解工厂模式普通的实现更加优雅的实现 总结 前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP快速入门与实战 学会好设计模式&#xff0c;能够对我们的技术水平得到非常大的提升。同时也会让我们的代码写的非常…

淘宝详情页分发推荐算法总结:用户即时兴趣强化

转子&#xff1a;https://juejin.cn/post/6992169847207493639 商品详情页是手淘内流量最大的模块之一&#xff0c;它加载了数十亿级商品的详细信息&#xff0c;是用户整个决策过程必不可少的一环。这个区块不仅要承接用户对当前商品充分感知的诉求&#xff0c;同时也要能肩负起…

Spark大数据处理学习笔记1.5 掌握Scala内建控制结构

文章目录 一、学习目标二、条件表达式&#xff08;一&#xff09;语法格式&#xff08;二&#xff09;执行情况&#xff08;三&#xff09;案例演示任务1、根据输入值的不同进行判断任务2、编写Scala程序&#xff0c;判断奇偶性 三、块表达式&#xff08;一&#xff09;语法格式…

Redis入门 - Lua脚本

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis入门 - Lua脚本 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-scription.html Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。 …