【进阶C语言】数组笔试题解析

本节内容以刷题为主,大致目录:

1.一维数组

2.字符数组

3.二维数组

学完后,你将对数组有了更全面的认识


在刷关于数组的题目前,我们先认识一下数组名:

数组名的意义:表示数组首元素的地址

但是有两个例外:

(1)sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。单位:字节。

(2)&数组名,这里的数组名表示整个数组,取出的是整个数组的大小。 

一、一维数组

1.判断下列sizeof计算的大小

(1)一维数组

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

结果展示:

代码分析:

#include<stdio.h>
int main()
{int a[] = { 1,2,3,4 };//一维数组//整形数组,每个元素4个字节,整个数组为16字节printf("%zd\n", sizeof(a));//数组名直接放在sizeof内部,表示整个数组的大小printf("%zd\n", sizeof(a + 0));//数组名没有单独放在sizeof内部,表示数组首元素的地址。大小就是4/8字节printf("%zd\n", sizeof(*a));//a就是首元素地址。*a==*(a+0)==a[0];所以*a就算首元素,大小为4字节printf("%zd\n", sizeof(a + 1));//a为首元素地址,+1跳过一个元素的地址,就算第二个元素的地址。a+1==&a[1]//只要是地址,就算4/8字节printf("%zd\n", sizeof(a[1]));//a[1]表示第二个元素,大小就是4字节printf("%zd\n", sizeof(&a));//&a,取出的是地址,只要是地址,就是4/8字节printf("%zd\n", sizeof(*&a));//*与&操作相互抵消。sizeof(*&a)==sizeof(a),为整个数组元素的大小==16字节printf("%zd\n", sizeof(&a + 1));//&a的结果是地址,+1操作后还是地址,那就是4/8字节printf("%zd\n", sizeof(&a[0]));//a[0]是第一个元素,&a[0]表示取出第一个元素的地址,地址就算4/8字节printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是首元素的地址,&a[0]+1就是第二个元素的地址,大小4/8个字节return 0;
}

 内存分局图:

总结:只要可以确定是地址,那么大小一定就是4/8字节

(2)字符数组

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

结果展示:

代码分析:

#include<stdio.h>
int main()
{char arr[] = { 'a','b','c','d','e','f' };//字符数组,每个元素大小1字节,整个数组大小6字节printf("%zd\n", sizeof(arr));//计算的是整个数组的大小,为6字节printf("%zd\n", sizeof(arr + 0));//计算的是地址,大小为4/8字节printf("%zd\n", sizeof(*arr));//*arr为第一个元素,大小为1字节printf("%zd\n", sizeof(arr[1]));//arr[1]表示第二个元素,大小为1字节printf("%zd\n", sizeof(&arr));//地址,4/8字节printf("%zd\n", sizeof(&arr + 1));//地址,4/8字节printf("%zd\n", sizeof(&arr[0] + 1));//地址,4/8字节return 0;
}

内存布局图:

(3)字符串数组

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

结果展示:

代码分析:

#include<stdio.h>
int main()
{char arr[] = "abcdef";//arr中的内容:a,b,c,d,e,f,\0printf("%zd\n", sizeof(arr));//整个数组大小:7字节printf("%zd\n", sizeof(arr + 0));//地址,4/8字节printf("%zd\n", sizeof(*arr));//首元素,1字节大小printf("%zd\n", sizeof(arr[1]));//第二个元素,1字节大小printf("%zd\n", sizeof(&arr));//地址,4/8字节printf("%zd\n", sizeof(&arr + 1));//地址,4/8字节printf("%zd\n", sizeof(&arr[0] + 1));//地址。4/8字节return 0;
}

内存分布图:

(4)单单字符串

char *p = "abcdef";
printf("%zd\n", sizeof(p));
printf("%zd\n", sizeof(p+1));
printf("%zd\n", sizeof(*p));
printf("%zd\n", sizeof(p[0]));
printf("%zd\n", sizeof(&p));
printf("%zd\n", sizeof(&p+1));
printf("%zd\n", sizeof(&p[0]+1));

结果展示:

代码分析:

#include<stdio.h>
int main()
{char* p = "abcdef";//p指向a的地址printf("%zd\n", sizeof(p));//p是指针,存放首字符a的地址,4/8字节printf("%zd\n", sizeof(p + 1));//p+1为字符b的地址,4/8字节printf("%zd\n", sizeof(*p));//*p==p[0],拿到的是第一个字符:a,为1字节printf("%zd\n", sizeof(p[0]));//求的是字符的大小,1字节printf("%zd\n", sizeof(&p));//地址,4/8字节printf("%zd\n", sizeof(&p + 1));//地址,4/8字节printf("%zd\n", sizeof(&p[0] + 1));//地址,4/8字节return 0;
}

内存分布图:

2.判断下列strlen计算的大小

知识点:strlen是计算字符串的长度(个数)的函数。统计的是在字符串中\0之前出现的字符的个数

(1)不带\0的字符数组

#include<stdio.h>
#include<string.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[1]));printf("%d\n", strlen(&arr));printf("%d\n", strlen(&arr + 1));printf("%d\n", strlen(&arr[0] + 1));return 0;
}

因为\0是strlen结束的标志,没有\0则不能正常计算

所以准确的来说,上述代码都是错误的。

错误原因解析:

#include<stdio.h>
#include<string.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[1]));//非法访问地址,错误代码printf("%d\n", strlen(&arr));//随机值。地址printf("%d\n", strlen(&arr + 1));//随机值。地址printf("%d\n", strlen(&arr[0] + 1));//随机值。地址return 0;
}

内存分布图: 

(2)自带\0的字符串数组

#include<stdio.h>
#include<string.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;
}

代码分析:

#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "abcdef";//arr中的数据:a,b,c,d,e,f,\0printf("%d\n", strlen(arr));//从起始位置开始计算长度,为6printf("%d\n", strlen(arr + 0));//从起始位置开始计算长度,为6printf("%d\n", strlen(*arr));//*arr==a,传入的值就为97,代码报错printf("%d\n", strlen(arr[1]));//arr[1]==b,传入的值为98,代码错误printf("%d\n", strlen(&arr));//从起始位置开始计算,长度为6printf("%d\n", strlen(&arr + 1));//&arr为起始地址,&arr+1跳过了整个数组,为随机值printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始,为5return 0;
}

内存分布图:

(3)带\0的纯字符串

#include<stdio.h>
#include<string.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;
}

代码分析:

#include<stdio.h>
#include<string.h>
int main()
{char* p = "abcdef";printf("%d\n", strlen(p));//从起始位置开始计算长度,为6printf("%d\n", strlen(p + 1));//从b位置开始计算长度,为5printf("%d\n", strlen(*p));//*p==a,传入97,代码报错printf("%d\n", strlen(p[0]));//代码报错printf("%d\n", strlen(&p));//&p为指针变量的地址,为随机值printf("%d\n", strlen(&p + 1));//&p+1跳过了该字符串,为随机值printf("%d\n", strlen(&p[0] + 1));//从b位置开始计算,长度为5return 0;
}

内存分布图:

二、二维数组

前言:二维数组的数组名同样是首元素地址,不过二维数组的首元素是第一行元素;而且依旧有两个例外。

题目:判断下列sizeof计算的大小

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

运行结果:

代码分析:

#include<stdio.h>
int main()
{int a[3][4] = { 0 };//三行四列,一行的大小是12,整个数组是48printf("%zd\n", sizeof(a));//数组名单独放在里面,计算的是整个数组的大小printf("%zd\n", sizeof(a[0][0]));//a[0][0]表示第一行第一列的元素,计算的是元素的大小,4字节printf("%zd\n", sizeof(a[0]));//a[0]表示第一行的地址,也可以称为第一行这个数组的数组名//sizeof(arr[0])计算的就是第一行整个一维数组的全部大小,16字节printf("%zd\n", sizeof(a[0] + 1));//a[0]没有单独存放,a[0]==&a[0][0],也表示第一行第一个元素的地址//所以a[0]+1==&a[0][1],地址就是:4/8字节printf("%zd\n", sizeof(*(a[0] + 1)));//a[0]+1为第二行元素的数组名,也是第二行元素的首元素,4字节printf("%zd\n", sizeof(a + 1));//a没有单独放在sizeof内部,所以表示第一行的地址//所以a+1是第二行的地址,4/8字节printf("%zd\n", sizeof(*(a + 1)));//a+1为第二行的地址,*(a+1)就是第二行//*(a+1)==a[1],第二行元素的总大小=4*4=16printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0]+1是第二行的地址//地址就是4/8字节printf("%zd\n", sizeof(*(&a[0] + 1)));//*(&a[0]+1)==a[1],计算的是第二行元素的大小,为16字节printf("%zd\n", sizeof(*a));//a没有单独放在sizeof内部,所以是第一行的地址//*a==a[0],计算的是第一行的元素,为16字节printf("%zd\n", sizeof(a[3]));//a[3]表示第四行元素,但是没有第四行元素//sizeof计算的只是类型大小,a[3]和a[0]或a[1]一样,都表示某一行元素//虽然没有第四行,但是跟a[0]的类型一样,都是四个int元素的数组return 0;
}

内存布局图:

总结:有二维数组a[3][4]

(1)a、a[0]、a[1]、a[2]都表示数组名

(2)a是二维数组的数组名,a[0]、a[1]、a[2]分别是第一、二、三行的数组名。

(3)第一、第二和第三行数组又可以称为一个一维数组

(4)a、a[0]、a[1]、a[2]单独放在sizeof内部或者&数组名,就表示整个数组

(5)没有像(4)那种,a、a[0]、a[1]、a[2]就表示首元素的地址

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

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

相关文章

Js基础——事件流

引入 当浏览器发展到第四代时&#xff08; IE4 及 Netscape Communicator 4 &#xff09;&#xff0c;浏览器开发团队遇到了一个很有意思 的问题&#xff1a;页面的哪一部分会拥有某个特定的事件&#xff1f;要明白这个问题问的是什么&#xff0c;可以想象画在一张纸上的一组…

vue3简易文字验证码

大神勿喷&#xff0c;简易版本&#xff0c;demo中可以用一下。 需要几个文字自己codelen 赋值 灵活点直接父组件传过去&#xff0c;可以自己改造 首先创建一个生成数字的js **mathcode.js**function MathCode(num){let str "寻寻觅觅冷冷清清凄凄惨惨戚戚乍暖还寒时候…

千兆以太网传输层 UDP 协议原理与 FPGA 实现(UDP接收)

文章目录 前言心得体会一、 UDP 协议简单回顾二、UDP接收实现三、完整代码展示四、仿真测试(1)模拟电脑数据发送,(2)测试顶层文件编写(3)仿真文件(4)仿真波形前言 在前面我们对以太网 UDP 帧格式做了讲解,UDP 帧格式包括前导码+帧界定符、以太网头部数据、IP 头部数…

光伏发电预测(LSTM、CNN_LSTM和XGBoost回归模型,Python代码)

运行效果&#xff1a;光伏发电预测&#xff08;LSTM、CNN_LSTM和XGBoost回归模型&#xff0c;Python代码&#xff09;_哔哩哔哩_bilibili 运行环境库的版本 光伏太阳能电池通过互连形成光伏模块&#xff0c;以捕捉太阳光并将太阳能转化为电能。因此&#xff0c;当光伏模块暴露…

windows 任务计划自动提交 笔记到github 、gitee

一、必须有个git仓库托管到git上。 这个就不用说了&#xff0c;自己在github或者码云上新建一个仓库就行了。 二、创建自动提交脚本 这个bat脚本是在windows环境下使用的。 注意&#xff1a;windows定时任务下 调用自动提交git前&#xff0c;必须先进入该git仓库目录&#x…

【Linux】线程控制

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ Linux       &#x1f6f0;️社区 :✈️ 进步学堂       &#x1f6f0…

DependsOn注解失效问题排查

文章目录 前言一、现象描述1.1.背景描述1.2.第一次修改&#xff0c;使用DependsOn注解1.3.第二次修改&#xff0c;设置方法入参 二、看看源码2.1.Spring实例化的源码2.2.调试2.3.验证 总结 前言 最近几天遇到一个比较有意思的问题&#xff0c;发现Spring的DependsOn注解失效&a…

CSS3与HTML5

box-sizing content-box&#xff1a;默认&#xff0c;宽高包不含边框和内边距 border-box&#xff1a;也叫怪异盒子&#xff0c;宽高包含边框和内边距 动画&#xff1a;移动translate&#xff0c;旋转、transform等等 走马灯&#xff1a;利用动画实现animation&#xff1a;from…

websocket拦截

python实现websocket拦截 前言一、拦截的优缺点优点缺点二、实现方法1.环境配置2.代码三、总结现在的直播间都是走的websocket通信,想要获取websocket通信的内容就需要使用websocket拦截,大多数是使用中间人代理进行拦截,这里将会使用更简单的方式进行拦截。 前言 开发者工…

【C++面向对象侯捷下】4. pointer-like classes,关于智能指针 | 5. function-like classes,所谓仿函数

文章目录 4. pointer-like classes,关于智能指针pointer-like classes,关于智能指针 shared_ptrpointer-like classes,关于迭代器5. function-like classes&#xff0c;所谓仿函数【不懂&#xff0c;跳过】 4. pointer-like classes,关于智能指针 pointer-like classes,关于智…

FFMPEG 视频类过滤器学习整理

针对FFMPEG提供视频过滤器进行了介绍,并提供使用实例 addroi 作用 在视频帧上标记一块感兴趣的区域。 帧数据被原封不动地传递,但元数据被附加到帧,指示可能影响后续编码行为的感兴趣区域。可以通过多次应用过滤器来标记多个区域。 参数 qoffset: 应用在此区域的量化偏…

C语言 - 数组

目录 1. 一维数组的创建和初始化 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存储 3. 数组越界 4. 数组作为函数参数 4.1…

电脑上制定工作计划的软件有哪些?

在数字的时代&#xff0c;电脑成为了我们工作的得力助手&#xff0c;但在这个信息过载的年代&#xff0c;如何在电脑上制定高效的工作计划成了工作中必不可少的一项任务。我在工作中也曾经迷茫过&#xff0c;制定的各项计划不能按时完成&#xff0c;直到我找到一款可以辅助我办…

tomcat整体架构

Tomcat介绍 Tomcat是Apache Software Foundation&#xff08;Apache软件基金会&#xff09;开发的一款开源的Java Servlet 容器。它是一种Web服务器&#xff0c;用于在服务器端运行Java Servlet和JavaServer Pages (JSP)技术。它可 以为Java Web应用程序提供运行环境&#x…

Linux读写锁的容易犯的问题

Linux读写锁的容易犯的问题 读写锁是互斥锁之外的另一种用于多线程之间同步的一种方式。 多线程对于一个共享变量的读操作是安全的&#xff0c; 而写操作是不安全的。如果在一个读很多而写很少的场景之下&#xff0c;那么使用互斥锁将会阻碍大量的线程安全的读操作的进行。在…

腾讯云轻量和CVM有啥区别?怎么选择服务器配置?

腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器价格便宜&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境&#xff0c;云服务器CV…

关于Jupyter markdown的使用

一级标题 #空格 标题1 二级标题 ## 空格 标题2 三级标题 ###空格 标题3 无序&#xff1b; 有序&#xff1a; 数学符号&#xff1a;

记一次问题排查

1785年&#xff0c;卡文迪许在实验中发现&#xff0c;把不含水蒸气、二氧化碳的空气除去氧气和氮气后&#xff0c;仍有很少量的残余气体存在。这种现象在当时并没有引起化学家的重视。 一百多年后&#xff0c;英国物理学家瑞利测定氮气的密度时&#xff0c;发现从空气里分离出来…

Visual Studio 2019中的安全问题

最近&#xff0c;在使用Visual Studio 2019的时候遇到了一个很奇怪的问题&#xff0c;如下所示。 这里一直在说scanf函数不安全&#xff0c;导致报错&#xff0c;然后上网查了查相关资料&#xff0c;发现在代码中加那么一句就可以了&#xff0c;而且必须放在最前面。 #define …

网工内推 | IT高级运维工程师,周末双休,包吃包住,14-20k

01 深圳朗特智能控制股份有限公司 招聘岗位&#xff1a;IT高级运维工程师 职责描述&#xff1a; 1、对集团网络基础架构的建设、运维、安全制定相关标准和准则&#xff1b; 2、负责集团数据中心、核心设备、信息安全的管理和运维&#xff1b; 3、执行网络、服务器、核心交换机…