C语言指针和数组相关习题

目录

  • sizeof和一维int数组
  • sizeof和一维char数组
  • strlen()和一维char数组
  • sizeof和字符串
  • strlen()和字符串
  • 指针变量指向字符串字面常量
  • 易错点sizeof('a'):sizeof是操作符 当心整型提升
  • sizeof和二维数组
    • 复习一下相关知识点
    • 练习题
  • 一个离谱的错误
  • 指针1
  • 指针2
  • 指针3
  • 指针4
  • 指针5
  • 指针6
  • 指针7
  • 指针8

sizeof和一维int数组

  • []的优先级比&高 所以&a[0]相当于&(a[0]) 取出了第一个元素的地址
  • a+0 既没有单独放在sizeof内部 也没有单独& 所以a就表示首元素地址 是一个int* a+0仍然是首元素地址 还是int* 也就是4/8
  • 同理 *a 也没有两个单独 所以就是首元素地址的解引用
  • sizeof(*&a):之前说过 对于一个数组指针解引用 结果就当做数组名来用 &a就是数组指针 *&a得到的就是数组名a *&a同样遵循两个单独的规则
  • &a+1 得到的结果不会改变:1.指针类型 2.权限
    所以 &a+1得到的还是一个数组指针(但本质也是个指针,地址)
  • 拓展:所以sizeof(*(&a+1)) 仍然相当于对数组指针解引用 得到的是一个"越界数组"的数组名 单独放在sizeof里 结果还是16
  • sizeof(sizeof(a+1)) === 4 不管内部sizeof在算什么 他的返回值肯定是size_t 即unsigned int 大小肯定是4字节

在这里插入图片描述

sizeof和一维char数组

这个就很简单了 都很明显
sizeof的核心就是 根据类型 在编译阶段就判断出大小了(字节)
在这里插入图片描述

strlen()和一维char数组

和上一题一模一样的数组 这次换成strlen
在这里插入图片描述

这里唯一要注意的就是strlen(*arr)
strlen接收的是地址!!
*arr其实得到字符a 本质上是97
strlen(97) 因为它接收的是一个地址 所以把97理解成地址了 非法访问!
0x00000061就等于十进制的97 97被理解成某个地址了 非法!!
那strlen(arr[1]) 也就是strlen(98) 是一样的道理
在这里插入图片描述

下面三个 &arr的地址值和&arr[0]和arr其实是一样的 只不过指针类型不一样
但是strlen是直接把你的值当做一个字符的地址的 也就是char* 然后从这个地址开始寻找\0
在这里插入图片描述
在这里插入图片描述

sizeof和字符串

在这里插入图片描述

  • 主要是字符串自带一个结束标志:‘\0’

在这里插入图片描述

strlen()和字符串

  • 注意倒数第二个 \0也是数组的一份子 +1把整个数组都跳过了 包括\0
    在这里插入图片描述

指针变量指向字符串字面常量

注意 这不是数组的形式了 p就是一个指针变量
在这里插入图片描述

下面就要注意strlen(&p)
&p是指针变量p的地址 跟"abcdef"毫无关系
随便拿了个地址就从那里开始找\0 肯定是随机值
在这里插入图片描述

易错点sizeof(‘a’):sizeof是操作符 当心整型提升

当成特例记住就行了 不要影响前面正常的理解

这个a的类型明明就是char 很难解释
只能这么理解:
sizeof就是个 操作符
sizeof(‘a’) 这就算char类型的’a’参与运算了
之前我们说过 这种情况就会发生整型提升

在这里插入图片描述

所以’a’还是会被sizeof理解成int类型 故答案是4
在这里插入图片描述

下图是一个类似的案例
在这里插入图片描述

● 其实不需要过于纠结 sizeof就看做求类型的大小
● 说明*p还是理解成char的
● 但是’a’被理解成int(97) 也有可能是’a’发生了整型提升
● 其实如果把这个文件改成.cpp 就是1了
所以不要纠结 知道sizeof就是求类型大小的就行

在这里插入图片描述
看一下CHatGPT的解释
认为’a’的本质是int 我觉得这个更合理
在这里插入图片描述

sizeof和二维数组

复习一下相关知识点

想象中的二维数组:
在这里插入图片描述

实际上的二维数组:
● a是整个二维数组的数组名 a的类型是数组指针
● 对数组指针解引用 得到的东西看做数组名 遵循两个单独 比如*&a
● arr[i]也是第i行一维数组的数组名
*(arr+i) == arr[i] 也表示第i行一维数组的数组名
● arr[i]和*(arr+i) 也遵守两个单独原则
在这里插入图片描述

练习题

a[0] == *(a+0) 对数组指针解引用 得到当前数组的数组名
就把他当成数组名来看待 也满足数组名所谓的"两个单独"
而且 指针+1不会改变指针的类型
a[0]+1 就是数组名+1 没有两个单独 所以就是当前一维数组的首元素地址+1
其实a[0]+1得到的是第一行一维数组的第二个元素的地址
在这里插入图片描述

● sizeof(a) 二位数组名单独放在sizeof里 表示整个二维数组大小(其实应该理解为 表示a[3][4]这种类型的大小)
●sizeof(a+1) 没有两个单独 所以a表示二维数组的首元素地址 即一维数组指针 +1跳过一个一维数组
且+1之后之类型和权限不变 变成了指向第二行一维数组的数组指针
●之前说过 把数组指针解引用理解成数组名 sizeof(*(a+1)) a+1是数组指针 解引用之后是数组名 其实就是sizeof(第二行一维数组的数组名) 也就是sizeof里面单独放了数组名(第二行一维数组的数组名) 算到16
或者从语法层面理解 *(a+1) = a[1] a[1]就是第二行的数组名 而且是单独放在sizeof里的
a+1 == &a[0]+1 都表示指向第二行一维数组的数组指针
&a[0]即&数组名 数组名单独在&之后 得到整个数组的地址 就是数组指针(指向第一行一维数组)
● &a[0]是数组指针 +1指针类型不变 *(&a[0]+1) 是对一个一维数组指针解引用 得到数组名 单独放在sizeof里 就是16
● sizeof(*a) 数组名a没有单独放在里面 所以a表示首元素地址(数组指针) *a对一维数组指针解引用 得到第一行一维数组的数组名 *a整体又是单独放在sizeof里的 相当于数组名单独放在sizeof内部 所以求的整个第一行一维数组的大小 即16
● 或者理解成:*a = *(a+0) = a[0]--->第一行数组名
● a[3]的确是越界了(但并没有解引用 所以不报错) 但是sizeof只关心类型 a[3]仍然被解读成*(a+3) 即对数组指针解引用 相当于把数组名单独放在sizeof内部 所以还是16
在这里插入图片描述

sizeof只关心类型 不会真的访问那块空间的 所以不会报错的
在这里插入图片描述

一个离谱的错误

一心想着&数组名 “单独"跟一个数组名
我就想着 如果不是单独 是不是就是二级指针了 居然写出了这种代码…
其实之前已经探讨过这个"牛角尖”
arr作为数组首元素地址 本质也是个指针/地址 也是个常量啊?
为什么就可以写&arr了 arr不也是常量吗?
所以才说他是特殊情况呢!!!
只有单独的时候才能用&+arr啊!!!
而且"单独"&arr 取出的就是整个数组的地址
对于一维数组来说 那就是一维数组指针
在这里插入图片描述

指针1

&a 单独+数组名 是一种特殊情况 取出整个数组的地址
数组指针+1 跳过一整个数组
但是跳完了类型又被强转成int*了 -1退后一个int 解引用访问一个int
答案:2,5
在这里插入图片描述

指针2

可能一上来第一个就算错了 算成:100001 这就错了 这不是数值的计算
这题考察的是:

  1. 指针+1 跳过几个内存单元(几个字节) 这取决于指针类型
  2. 数值+1 那就是单纯的+1 学了指针不要忘记正常的情况了
  3. 结构体内存对齐 怎么计算结构体的大小(才知道结构体指针+1跳过几个字节)
  4. 32位机器 指针4字节 %p打印即8个十六进制位 所以答案还要自己补0!! 细节!!
  5. 如果用 %x单纯打印16进制 前面的0没有数值意义 就会省略

答案:00100014,00100001,00100004
第二个这个地址就被当成一个无符号的数了(0x100000只不过是用16进制来表示了一个整数) 进行的是数值± +1那就是单纯的+1
在这里插入图片描述
在这里插入图片描述

指针3

内存中的存储(小端):
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
ptr1[-1] = *(ptr1-1)
%x是打印十进制对应的十六进制补码 只打印有效位(高位没意义的0不打印)
%p其实也是打印十进制对应的十六进制补码 不过我们一般用%p专门打印地址 地址肯定是4字节 也就是8个十六进制位 不足8位会补齐
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ptr1-1会跳过一个int 指向04的内存单元
再*(ptr-1) 权限是一个int
又拿到一个int 就是4
在这里插入图片描述
在这里插入图片描述

指针4

注意逗号表达式!!! 这是不完全初始化!!!
arr[0] 即第一行元素的数组名(他也遵守两个单独的规则)
int *p = a[0] 类似之前一维数组写的int* parr = arr
这里的a[0]并没有两个单独 就表示首元素地址 把首元素地址赋给p了
p指向 [1,3]这个一维数组的首元素地址 p[0] = *(p+0) = *p = 1
在这里插入图片描述

指针5

这里主要就是要知道 p[4][2] 和 a[4][2]指向哪里去了?
a[4][2]很好理解 这里对于p[4][2] 有两个看待角度:

  1. p[4][2] 即在p的视角下的二维数组的第五行第三列 对于p来说 每一行应该是四个元素 所以找到第五行就是每次跳过四个元素 跳四次 然后再找第三个元素 只要画好图 很好找
  2. 从理论上理解 p[4][2] = *(p+4)[2] = *(*(p+4)+2)
    p的类型是int(*)[4]的数组指针 p+1 每次跳过一个数组 即四个int 且类型保持不变 那么p+4 就是跳过四个数组 即16个int
    p+4之后 类型不变 还是数组指针 指向一个新的数组
    *(p+4) 对数组指针解引用 得到当前数组的数组名 那么*(p+4)[2]也就是当前数组第三个元素
    如果要进一步理解*(*(p+4)+2)
    这里*(p+4)这个数组名没有单独规则 所以就表示当前数组的首元素地址
    *(p+4)+2 相当于arr+2 指向第三个元素 再解引用 就拿到第三个元素

下面又把元素的地址取出来相减了
指针-指针的绝对值求的是隔了几个元素
算到-4

在这里插入图片描述
在这里插入图片描述

打印的时候
不管是%d 还是%p %x %X 都是针对存的补码去打印
只不过%d打印的时候 把补码当做有符号数打印 需计算原码
而地址没有什么原反补 就是直接把存起来的补码 当成一个地址打印(地址一般用16进制表示)
在32位机器 也就是打印8个十六进制位
在这里插入图片描述
%x打印的也是二进制补码
在这里插入图片描述

指针6

arr是数组指针 arr+1跳过一整个数组 *(arr+1) 其实就是得到了第二个数组的数组名
*(arr+1)又等于arr[1]arr[i]得到的就是第i个一维数组的数组名
所以ptr2 = (int*)arr[1] 即(int*)第二个一维数组的数组名
在这里插入图片描述

指针7

int* *p p的类型是int**--(二级)指针 p+1跳过1个int*(地址)
● 数组里放的分别是:w的地址 a的地址 a的地址
● 数组名表示首元素地址 也就是w的地址的地址 --二级指针
● pa++ 即跳过一个char*(地址) 把图画好 解引用pa得到的其实是at的a的地址在这里插入图片描述

在这里插入图片描述

指针8

  • 注意++操作符 是有副作用的 会真的改变值
    在这里插入图片描述
    在这里插入图片描述

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

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

相关文章

Centos安装ZooKeeper教程(单机版)

本章教程介绍,如何在Centos7中,安装ZooKeeper 3.9.3版本。 一、什么是ZooKeeper ? Apache ZooKeeper 是一个分布式协调服务,用于大型分布式系统中的管理和协调。它为分布式应用提供了一个高性能的通信框架,简化了开发人员在构建复杂分布式系统的任务。ZooKeeper 能够解决一…

出国工作——常用英语——网站注册

Please set your password for your new Qt Account. Password must be at least 8 characters in length. 请为您的新 Qt 账户设置密码。密码长度必须至少为 8 个字符。 Password Password strength: BadThis is similar to a commonly used password. TIP: Add another wor…

江协科技STM32学习- P25 UART串口协议

🚀write in front🚀 🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝​…

Servlet 3.0 新特性全解

文章目录 Servlet3.0新特性全解Servlet 3.0 新增特性Servlet3.0的注解Servlet3.0的Web模块支持servlet3.0提供的异步处理提供异步原因实现异步原理配置servlet类成为异步的servlet类具体实现异步监听器改进的ServletAPI(上传文件) Servlet3.0新特性全解 tomcat 7以上的版本都支…

mysql 通过GROUP BY 聚合并且拼接去重另个字段

我的需求: 我想知道同一个手机号出现几次,并且手机号出现在哪些地方。下面是要的效果。 源数据: CREATE TABLE bank (id bigint(20) unsigned NOT NULL AUTO_INCREMENT,user_id int(11) NOT NULL DEFAULT 0,tel varchar(255) COLLATE utf8mb4_unicode_…

新加坡托管服务器VS香港托管服务器:AI时代的选择策略

在人工智能迅速发展的今天,服务器作为数据存储与计算的核心基础设施,其性能、稳定性和地理位置对于用户体验和业务效率至关重要。对于中国用户而言,在选择服务器时,新加坡服务器和香港服务器无疑是两个极具吸引力的选项。两者同属…

Linux的硬盘管理

硬盘有价,数据无价 1. 硬盘的概念 硬盘是一种计算机的存储设备,通常是由一个或者多个磁性盘片组成。硬盘即可以安装在计算机的内部,也可以外接计算机。 保存数据 数据:操作系统,应用程序,文档多媒体文件…

震惊,盖子居然重现CSDN?

盖子奇迹般重回C站 众所周知,盖子上次发布文章是在2024年5月18号(感兴趣的可以回去看一下,链接放在下面了) 盖子的c小课堂——第二十七讲:背包变形题_恰好装满的01背包-CSDN博客https://blog.csdn.net/m0_73334782/a…

PostgreSQL的学习心得和知识总结(一百五十七)|新的 COPY 选项 LOG_VERBOSITY

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…

【力扣打卡系列】二叉树的最近公共祖先

坚持按题型打卡&刷&梳理力扣算法题系列,语言为go,Day18 二叉树的最近公共祖先 题目描述 解题思路 最近公共祖先分类讨论 当前节点是空节点(返回当前节点)当前节点是p(返回当前节点)当前节点是q&am…

Redis常见面试题总结(上)

Redis 基础 什么是 Redis? Redis (REmote DIctionary Server)是一个基于 C 语言开发的开源 NoSQL 数据库(BSD 许可)。与传统数据库不同的是,Redis 的数据是保存在内存中的(内存数据库,支持持久…

Training-free layout control with cross-attention guidance

https://zhuanlan.zhihu.com/p/666445024https://zhuanlan.zhihu.com/p/666445024 支持两种模式,1.sd文生图;2.绑定了dreambooth和text inversion的图像编辑。 # ------------------ example input ------------------examples &

‌Spring MVC的主要组件有哪些?

前言 SpringMVC的核心组件包括DispatcherServlet、Controller、HandlerMapping、HandlerAdapter、ViewResolver、ModelAndView等,它们协同工作以支持基于MVC架构的Web应用程序开发。这些组件使得开发人员能够以一种声明式和模块化的方式构建Web应用程序&#xff0c…

Python突破浏览器TLS/JA3 指纹

初识指纹遇到一个网站,忽然发现无论如何如何更换UA和代理请求都是403,curl_cffi 可模拟真实浏览器的 TLS | JA3 指纹。 查看 tls 指纹的网站: https://tls.browserleaks.com/json不同网站的生成的指纹可能有差异,但是多次访问同一个网站生成…

Redis新数据类型

新数据类型 Bitmaps 命令 setbit 实例 getbit 实例 bitcount 实例 bitop 实例 Bitmaps与set 对比 HyperLogLog 命令 pfadd 实例 pfcount 实例 pfmerge 实例 Geospatial 命令 geoadd 实例 geopos 实例 geodist 实例 georadius 实例 Bitmaps Ⅰ.B…

【Qt】QTableView添加下拉框过滤条件

实现通过带复选框的下拉框来为表格添加过滤条件 带复选框的下拉框 .h文件 #pragma once #include <QCheckBox> #include <QComboBox> #include <QEvent> #include <QLineEdit> #include <QListWidget>class TableComboBox : public QComboBox …

Java Executor ScheduledExecutorService 源码

前言 相关系列 《Java & Executor & 目录》《Java & Executor & ScheduledExecutorService & 源码》《Java & Executor & ScheduledExecutorService & 总结》《Java & Executor & ScheduledExecutorService & 问题》 涉及内容 …

C++:继承~派生类以及衍生的多继承与菱形继承问题

C中的继承其实是一个C中的坑,主要体现在其多继承(菱形继承)方面,我们先来了解下继承的概念 一,继承的概念与定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许我们在保持原有类特性的基础上进行扩展&#xff0c;增…

Python 从入门到实战43(Pandas数据结构)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;可以熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们学习了NumPy数组操作的相关基础知识。今天学习一下pa…

工程项目智能化管理平台,SpringBoot框架智慧工地源码,实现工程建设施工可视化、智能化的全过程闭环管理。

智慧工地管理系统的建设以“1个可扩展性平台2个应用端3方数据融合N个智能设备”为原则。以“智、保、安、全”为导向&#xff0c;与工程建设管理信息系统、综合安防平台深度集成&#xff0c;构建统一的标准化工地平台&#xff0c;实现现场人员、车辆、项目、安全、进度等方面的…