C语言指针详解(3)———指针题目,你确定你学会指针了?进来看看吧!(几十个指针小题+超详解)

你确定你学会指针了? 你确定你明白数组名了?
如果你觉得你学的还不错,就进来看看吧,相信你看完之后一定能收获更多。

数组名的理解一定要弄清楚
数组名是数组首元素的地址 但是有2个例外:

  1. sizeof(数组名),这里的数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节
  2. &数组名,这里的数组名表示整个数组,&数组名取出的是数组的地址

下面是常见 指针和数组笔试题及解析 (解析以注释的形式写在代码当中)
下面题目的类型都是给你一个数组,你来判断printf到底输出什么。

int main()
{//一维数组int a[] = { 1,2,3,4 };//4个元素,每个元素4个字节(int类型)printf("%d\n", sizeof(a));//16   //数组名a单独放在sizeof内部,数组名表示整个数组,计算的是整个数组的大小单位是字节,是16字节printf("%d\n", sizeof(a + 0));//4///a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+0还是首元素的地址printf("%d\n", sizeof(*a));//4//a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,*a是首元素,相当于a[0]printf("%d\n", sizeof(a + 1));//4//a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+1就是第二个元素的地址,相当于a[1]printf("%d\n", sizeof(a[1]));//4//a[1]就是数组的第二个元素,这里计算的就是第二个元素的大小printf("%d\n", sizeof(&a));//4//是取出数组的地址,但是数组的地址也是地址,是地址就是4/8个Byte,数组的地址和数组首元素的地址的本质区别是类型的区别,并非大小的区别//a  -- int*             int * p = a;//&a -- int (*)[4]       int (*p)[4] = &a;printf("%d\n", sizeof(*&a));//16//对数组指针解引用访问一个数组的大小,即*(解引用)和&(取地址)可以相互抵消,sizeof(*&a)==sizeof(a)printf("%d\n", sizeof(&a + 1));//4//&a数组的地址,&a+1还是地址,此时指向的是数组中a[3](4)后面的地址(数组指针+1跳过一个数组)printf("%d\n", sizeof(&a[0]));//4//&a[0]是首元素的地址printf("%d\n", sizeof(&a[0] + 1));//4//&a[0]是首元素的地址,&a[0]+1就是第二个元素的地址return 0;
}
int main()
{//字符数组char arr[] = { 'a','b','c','d','e','f' };//6个字符printf("%d\n", sizeof(arr));//6//数组名arr单独放在sizeof内部,计算的是整个数组的大小printf("%d\n", sizeof(arr + 0));//4//arr是首元素的地址==&arr[0],是地址就是4个字节,指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节printf("%d\n", sizeof(*arr));//1//arr是首元素的地址,*arr就是首元素printf("%d\n", sizeof(arr[1]));//1//第二个元素printf("%d\n", sizeof(&arr));//4//&arr是数组的地址,只要是地址就是4/8,sizeof(&arr)就是4/8个字节printf("%d\n", sizeof(&arr + 1));//4//&arr+1 是跳过数组后的地址,即f后的地址printf("%d\n", sizeof(&arr[0] + 1));//4//第二个元素的地址,是地址就是4/8//strlen是求字符串长度的函数,统计的是在字符串中\0之前出现的字符的个数printf("%d\n", strlen(arr));//随机值(>=6)//arr是首元素的地址,往后走不确定到哪里才能到\0,字符数组不像整型数组一样最后一个数字后面就是\0,字符数组的\0不知道在后面什么地方printf("%d\n", strlen(arr + 0));//随机值(>=6)//arr是首元素的地址, arr+0还是首元素的地址printf("%d\n", strlen(*arr));//非法访问,错误//arr是首元素的地址, *arr就是首元素 - 'a'的ASCLL码 - 97,站在strlen的角度,认为传参进去的'a'-97就是地址,97作为地址,直接进行访问,就是非法访问printf("%d\n", strlen(arr[1]));//非法访问,错误//'b' 的ASCLL码- 98,错误与上面相同printf("%d\n", strlen(&arr));//随机值(不知道/0在哪里)//取出的是整个数组的地址,&arr取出的类型是 char (*)[6](数组指针类型),strlen的参数类型是const char*,编译器会报警告但是不影响,类型发生了变化但是值不变。printf("%d\n", strlen(&arr + 1));//随机值//&arr+1,是f后的地址(跳过了整个数组),不知道什么时候遇到/0,所以也是随机值printf("%d\n", strlen(&arr[0] + 1));//随机值//一个字符的地址+1,是b的地址,后面不知道/0在哪里,也是随机值return 0;
}
int main()
{char arr[] = "abcdef";//a b c d e f /0printf("%d\n", sizeof(arr));//7//abcdef和/0一共七个元素printf("%d\n", sizeof(arr + 0));//4//首元素地址+0还是首元素地址printf("%d\n", sizeof(*arr));//1//首元素地址解引用,还是首元素a,一个字节printf("%d\n", sizeof(arr[1]));//1//第二个元素,一个字节printf("%d\n", sizeof(&arr));//4//数组的地址,为4/8printf("%d\n", sizeof(&arr + 1));//4//跳过整个数组的地址,为/0后的地址,是地址就是4/8printf("%d\n", sizeof(&arr[0] + 1));//4//第一个元素的地址+1,就是第二个元素的地址,是地址就是4/8printf("%d\n", strlen(arr));//6//首元素地址传给strlen,往后数因为有/0,所以是6printf("%d\n", strlen(arr + 0));//6//首元素地址+0,还是首元素地址,往后数,因为有/0,所以是6printf("%d\n", strlen(*arr));//非法访问,错误//对首元素地址解引用,其实就是字符a,传进去的是a的ASCLL码值97,会报错printf("%d\n", strlen(arr[1]));//非法访问,错误//传进去的是第二个元素b,穿的是b的ASCLL码,会报错printf("%d\n", strlen(&arr));//6//传进去的是首元素的地址,往后数,因为有/0,所以是6printf("%d\n", strlen(&arr + 1));//随机值//首元素的地址+1,跳过整个数组,即到/0之后,/0之后什么时候遇到下一个/0不知道,为随机值printf("%d\n", strlen(&arr[0] + 1));//5//第二个元素的地址,从b数到/0,有5个return 0;
}
int main()
{char* p = "abcdef";//a b c d e f \0,但p中存放的是a的地址(p能够找到abcdef/0)printf("%d\n", sizeof(p));//4//计算的是指针变量的大小printf("%d\n", sizeof(p + 1));//4//char*指针+1向后偏移一个,但p+1还是一个地址,是地址就是4/8printf("%d\n", sizeof(*p));//1//  *p=='a'printf("%d\n", sizeof(p[0]));//1//p[0]等价于*(p+0),等价于*p,即第一个元素aprintf("%d\n", sizeof(&p));//4//&p仍然是一个地址,是地址就是4/8,假设p的地址是0x0012fc60,指向的就是0x00的地址,类型是char**二级指针printf("%d\n", sizeof(&p + 1));//4//&p是地址,&p+1还是地址,是地址就是4/8,假设p的地址是0x0012fc60,指向的就是0x60,类型是char**二级指针printf("%d\n", sizeof(&p[0] + 1));//4//指向第二个元素的地址,是地址就是4/8printf("%d\n", strlen(p));//6//a的地址往后数到/0printf("%d\n", strlen(p + 1));//5//b的地址往后数到/0printf("%d\n", strlen(*p));//非法访问,错误//p指向a的地址,*p就是a,传的a的ASCLL码,错误printf("%d\n", strlen(p[0]));//非法访问,错误//和*p一样的,是a,传的a的ASCLL码,错误printf("%d\n", strlen(&p));//随机值//&p假设取的是0x0012ff40,这个指针变量占4个字节,即从0x0012ff40往后找/0,后面什么位置有/0不知道printf("%d\n", strlen(&p + 1));//随机值//&p假设取的是0x0012ff40,&p+1指的是0x40后的地址,即从0x40往后找/0,后面什么位置有/0不知道printf("%d\n", strlen(&p[0] + 1))//5//第二个元素b的地址,往后数到/0,有五个return 0;
}
int main()
{//二维数组int a[3][4] = { 0 };printf("%d\n", sizeof(a));//48//数组名a单独放在sizeof内部,表示整个数组,一共3*4=12个元素,每个元素4个字节即12*4=48printf("%d\n", sizeof(a[0][0]));//4//a[0][0]是数组的第一行第一列的元素printf("%d\n", sizeof(a[0]));//16//二维数组其实是一维数组的数组,a[0]可以看成第一行的元素,a[1],a[2]可以看成二三行的元素,即整个第一行的大小,即4*4=16printf("%d\n", sizeof(a[0] + 1));//4//a[0]并非放在sizeof内部,所以a[0]表示数组首元素的地址,也就是第一行第一个元素的地址。a[0]+1表示a[0][1]的地址。是地址就是4/8printf("%d\n", sizeof(*(a[0] + 1)));//4//a[0]+1是a[0][1]的地址,解引用就是第二个元素printf("%d\n", sizeof(a + 1));//4//a作为二维数组的数组名,名没有单独放在sizeof内部,a就是首元素的地址,也就是第一行的地址。a+1就是第二行的地址,a的类型是一个数组指针int(*)[4],是地址就是4/8printf("%d\n", sizeof(*(a + 1)));//16//a+1是第二行的地址,解引用就是第二行  4*4=16printf("%d\n", sizeof(&a[0] + 1));//4//a[0]是第一行的数组名,&a[0]取出的是数组的地址,取出的是第一行这个一维数组的地址,类型就是int(*)[4],&a[0]+1就是第二行的地址,是地址就是4/8printf("%d\n", sizeof(*(&a[0] + 1)));//16//对第二行的地址解引用就是第二行,4*4=16printf("%d\n", sizeof(*a));//16//a没有单独放在sizeof内,a表示数组首元素的地址,也就是第一行的地址,解引用就代表第一行,4*4=16printf("%d\n", sizeof(a[3]));//16//a[3]表示第四行,按理说应该越界了,但是没有,sizeof是计算,不会去真的访问第四行,其相当于和a[0]一样,4*4=16return 0;
}

总结

指针和数组名在C语言中非常重要,它们是C语言中最基本的数据类型和数据结构之一。以下是指针和数组名的重要性:

1.内存管理:指针允许我们直接访问和操作内存中的数据。通过指针,我们可以动态地分配和释放内存,有效地管理内存资源。

2.数组访问:数组名本质上是一个指向数组第一个元素的指针。通过数组名,我们可以方便地访问和操作数组中的元素。

3.函数参数传递:通过指针作为函数参数,可以实现对函数外部变量的修改。这在需要在函数内部修改变量的值时非常有用。

4.字符串处理:C语言中的字符串是以null字符结尾的字符数组。通过指针和数组名,我们可以方便地处理字符串,比如拷贝、连接、比较等操作。

5.动态数据结构:指针可以用来创建和操作动态数据结构,比如链表、树等。通过指针,我们可以动态地创建和销毁节点,连接和遍历节点。

6.性能优化:在一些需要高效处理大量数据的场景中,通过指针和数组名可以减少内存拷贝和数据移动的开销,提高程序的执行效率。

总的来说,指针和数组名在C语言中扮演着非常重要的角色,它们是C语言实现高效、灵活和可靠的关键工具。在学习和使用C语言时,理解和掌握指针和数组名的概念和用法是非常重要的。

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

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

相关文章

【MySQL多表查询以及事务、索引】

1. 多表查询 1.1 概述 1.1.1 数据准备 #建议:创建新的数据库 create database db04; use db04;-- 部门表 create table tb_dept (id int unsigned primary key auto_increment comment 主键ID,name varchar(10) not null unique comment 部门名称…

Jmeter 实现 mqtt 协议压力测试

1. 下载jmeter,解压 https://jmeter.apache.org/download_jmeter.cgi 以 5.4.3 为例,下载地址: https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.4.3.zip linux下解压: unzip apache-jmeter-5.4.3.zip 2. 下载m…

proxy相对于object.defineproperty有哪些优点?

Proxy相对于Object.defineProperty的优点有1: 功能更强大:Proxy提供了更灵活的方式来操作对象,可以捕获和定制对象的各种操作,包括获取属性、设置属性、删除属性等。捕获多种操作:Proxy可以捕获多种不同的操作&#x…

在线海报图片设计器、图片编辑器源码/仿照稿定设计源码

在线海报设计系统素材设计源码是一个漂亮且功能强大的在线海报图片设计器,仿照稿定设计而成。该系统适用于多种场景,包括海报图片生成、电商分享图、文章长图、视频/公众号封面等。用户无需下载软件,即可轻松实现创意,迅速完成排版…

使用 React Native 针对 Android 进行开发

🎬 岸边的风:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 概述 通过安装所需工具开始使用 React Native 创建新的 React Native 项目 本指南将有助于开始使用 Windows 上的…

性能测试工具有哪些?原理是什么?怎么选择适合的工具?

前言 本篇文章主要简单总结下性能测试工具的原理以及如何选型。性能测试和功能测试不同,性能测试的执行是基本功能的重复和并发,需要模拟多用户,在性能测试执行时需要监控指标参数,同时性能测试的结果不是那么显而易见&#xff0…

43.228.64.X游戏盾在业务高峰时间段,出现用户大量掉线问题,可能是什么原因导致

服务器负载过高:业务高峰期间,服务器可能无法处理大量的用户请求,导致性能下降,甚至引起服务器崩溃,从而导致用户掉线。 网络带宽不足:当大量用户同时访问游戏盾时,网络带宽可能不足以支持所有…

Smart Community(1)之设计规范

通过前面大数据开发相关知识的学习,准备做一个项目进行练习---我给他起了一个响亮的名字:基于HadoopHA的智慧社区服务平台 设计规范: 做一个项目之前肯定要先规定一些开发过程中的设计规范 (一)数据埋点规范&#xf…

linux jenkins2.414.1-1.1版本安装

文章目录 前言一、rpm文件下载二、安装jenkins2.1.升级jdk1.82.2安装jenkins2.3 启动服务2.4 使用密码登录2.5 修改插件源2.6 汉化插件安装演示 总结 前言 之前也安装过jenkins,但是那个版本是2.1的,太老了很多插件都不支持,现在安装目前为止…

XSS笔记

一、xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中&#xff0c;通过用户本地浏览器执行的&#xff0c;所以xss漏洞关键就是寻找参数未过滤的输出函数。 二、XSS的攻击方式 1、 反射型XSS&#xff1a;<非持久化> 攻击者事先制作好攻击链接, 需要欺骗用…

RocketMq(一)安装部署

一、linux单机部署&#xff1a; 1、到apache官网下载 | RocketMQ (apache.org)下载binary zip包&#xff0c;如我下载的4.9.6版本。 上传到建好的/usr/local/rocketmq目录下。 2、解压zip包 unzip rocketmq-all-4.9.6-bin-release.zip 3、进入解压后的文件夹,启动 Name Serv…

vue之$emit返回值

使用场景&#xff1a;子组件调用父组件的方法并获取到父组件方法的返回值 方法(一): 回调函数: 1.子组件方法&#xff1a; ……methods:{ShowMore(step){this.$emit("ChildClick",step,(res)>{//回调函数的方法体.处理自己的业务.});}}…… 2、父组件方法 ……

java23种设计模式与追MM

1、FACTORY—追MM少不了请吃饭了&#xff0c;麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西&#xff0c;虽然口味有所不同&#xff0c;但不管你带MM去麦当劳或肯德基&#xff0c;只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory 工厂模式&#xff1a…

02目标检测-传统检测方法

目录 一、目标学习的检测方法变迁及对比 二、 基于传统手工特征的检测算法的定义 三、传统主要手工特征与算法 Haar特征与 人脸检测算法 - Viola-Jones(了解) HOG特征与 SVM 算法(了解)&#xff08;行人检测、opencv实现&#xff09; SIFT特征与SIFT算法(了解) DPM&#…

redis--windows配置--redis基础

写在前面&#xff1a; 文章目录 win安装配置密码配置服务服务已经存在 可视化工具运行类型基础类型 帮助文档命令通用命令string命令hashlistsetsortedset win安装 下载地址 然后一路next就可以了。 记得添加到环境变量 配置密码 在目录打开配置文件 搜索requirepass …

Fluent实现大量气泡的随机分布案例

1、问题介绍 气液两相管流在石油、化工、能源、制冷等工业领域中大量存在。气泡在生存发展过程中往往会导致噪声和引起管道振动&#xff0c;自来水管路中如有空气时往往会产生啸叫声和管道剧烈振动。掌握流动过程中气泡的生成、发展及其破裂等动力规律是控制气液两相流气动噪声…

C++qt day8

1.用代码实现简单的图形化界面&#xff08;并将工程文件注释&#xff09; 头文件 #ifndef MYWIDGET_H #define MYWIDGET_H //防止头文件冲突#include <QWidget> //父类的头文件class MyWidget : public QWidget //自定义自己的界面类&#xff0c;公共继承…

【pygame】01 pygame制作游戏的最小系统

这次使用sublimepython进行pygame的游戏开发&#xff0c;目的是学习使用python的基本操作和常用模块 添加一个文件夹到工程 最小系统 1.导入使用的模块 2.初始化&#xff1a;pygame.init函数包含了各个子模块的初始化&#xff0c;可以重复调用 3.pygame.display.set_mode返…

<OpenCV> Mat属性

OpenCV的图像数据类型可参考之前的博客&#xff1a;https://blog.csdn.net/thisiszdy/article/details/120238017 OpenCV-Mat类型的部分属性如下&#xff1a; size&#xff1a;矩阵的大小&#xff0c; s i z e ( c o l s , r o w s ) size(cols,rows) size(cols,rows)&#xf…

Java手写选择排序和算法案例拓展

Java手写选择排序和算法案例拓展 1. Mermanid代码表示思维导图解释实现思路原理 #mermaid-svg-uD2bB5QreLEC3dsv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-uD2bB5QreLEC3dsv .error-icon{fill:#552222;}#merm…