【C语言进阶(4)】指针和数组笔试题

文章目录

  • Ⅰ 一维数组
  • Ⅱ 字符数组
    • 题型 1
    • 题型 2
    • 题型 3
  • Ⅲ 二维数组

数组名的意义

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示的是整个数组,取出的是整个数组的地址。
  3. 除了上述两种情况之外,所有的数组名表示的都是数组首元素的地址。

Ⅰ 一维数组

int a[] = { 1,2,3,4 };printf("%zd\n", sizeof(a));			//16		
//sizeof(数组名),计算的是整个数组的大小printf("%zd\n", sizeof(a + 0));		//4/8	
//此处的 a + 0 表示数组首元素的地址,是地址就是 4/8 个字节printf("%zd\n", sizeof(*a));		//4
//*a 中的 a 是数组首元素的地址,*a 就是对首元素的地址解引用;
//找到的就是首元素,首元素的大小就是 4 个字节printf("%zd\n", sizeof(a + 1));		//4/8
//a + 1 表示数组第二个元素(2)的地址,所以计算结果是 4/8 个字节printf("%zd\n", sizeof(a[1]));		//4
//计算第二个元素的大小printf("%zd\n", sizeof(&a));		//4/8
//&a 取出的是整个数组的地址,数组的地址它还是个地址,是地址就是 4/8 个字节printf("%zd\n", sizeof(*&a));		//16
//* 与 & 相互抵消,就成了 sizeof(a) 计算整个数组的大小printf("%zd\n", sizeof(&a + 1));	//4/8
//&a 取出整个数组的地址,&a 的类型 是 int(*)[4];
//&a + 1是从数组 a 的地址向后,跳过了一个 4 个整型元素的数组的大小;
//&a + 1 还是地址,是地址就是 4/8 个字节printf("%zd\n", sizeof(&a[0]));		//4/8
//计算的是第一个元素的地址printf("%zd\n", sizeof(&a[0] + 1));	//4/8
//&a[0] + 1 是第二个元素的地址

Ⅱ 字符数组

题型 1

char arr[] = { 'a','b','c','d','e','f' };//整个数组 6 个元素

1. 用 sizeof 求结果

char arr[] = { 'a','b','c','d','e','f' };printf("%zd\n", sizeof(arr));			//6
//整个数组的大小为 6 个字节printf("%zd\n", sizeof(arr + 0));		//4/8
//不是 sizeof(单个数组名)这种情况,arr + 0 表示首元素地址,地址都是 4/8 个字节printf("%zd\n", sizeof(*arr));			//1
//*arr 就是数组的首元素,大小事 1 字节printf("%zd\n", sizeof(arr[1]));		//1
//计算的是数组第二个元素的大小,'b' 的大小为 1 字节printf("%zd\n", sizeof(&arr));			//4/8
//计算整个数组的地址,是地址就是 4/8 字节printf("%zd\n", sizeof(&arr + 1));		//4/8
//&arr + 1 指向了 'f' 的后面,但它还是个地址printf("%zd\n", sizeof(&arr[0] + 1));	//4/8
//计算第二个元素的地址,地址的大小都是 4/8 个字节

2. 用 strlen 求结果

char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));			随机值
//strlen 会计算 '\0' 之前有几个字符,arr 里面并没有 '\0';
//strlen 会一直往后找 '\0',直到碰巧碰到 '\0' 才停止工作。printf("%d\n", strlen(arr + 0));		随机值
//arr 还是首元素地址,指向 'a',这玩意不是 '\0',strlen 自然要往后猛找 '\0'printf("%d\n", strlen(*arr));			程序报错(野指针问题)
//站在 strlen 这个函数的角度看,传给它的都应该是地址,然而 *arr 是 'a'(97);
//相当于 strlen(97),把 97 作为一个地址传给 strlen,那肯定会出 BUGprintf("%d\n", strlen(arr[1]));			程序报错(野指针问题)
//和上面类似,相当于 strlen(98),把 98 当做地址传给 strlen,不出 BUG 才有问题printf("%d\n", strlen(&arr));			随机值
//数组的地址从 'a' 开始,还是没有 '\0',strlen 又要吭哧吭哧往后找了printf("%d\n", strlen(&arr + 1));		随机值 - 6
//传过去的地址指向 'f' 后面,从 'f' 后面开始往后找 '\0',那必定是个随机值了。
//又因为是从 'f' 后面开始往后找,没有算入 arr 数组内的 6 个字符所以随机值会少 6printf("%d\n", strlen(&arr[0] + 1));	随机值 -1
//从 'b' 的地址处开始往后找,没有算入 'a' 这一个字符的个数

题型 2

char arr[] = "abcdef";//这个数组有 a b c d e f \0 7 个元素

1. 用 sizeof 求结果

char arr[] = "abcdef";printf("%zd\n", sizeof(arr));			//7
//'f' 的后面藏了个 '\0',所以整个数组的大小是 7 个字节printf("%zd\n", sizeof(arr + 0));		//4/8
//sizeof 内不是单个数组名这种情况,所以 arr + 0 表示的首元素的地址,地址就是 4/8 字节
printf("%zd\n", sizeof(*arr));			//1
//arr 是首元素地址,对首元素地址解引用就得到了 'a',这个字符的大小就是 1 字节printf("%zd\n", sizeof(arr[1]));		//1
//arr[1] 是字符 'b','b' 的大小位 1 字节printf("%zd\n", sizeof(&arr));			//4/8
//这个数组的地址还是地址,是地址就是 4/8 字节printf("%zd\n", sizeof(&arr + 1));		//4/8
//&arr + 1 指向了 '\0' 的后面,即使指向 '\0' 后面它还是个地址printf("%zd\n", sizeof(&arr[0] + 1));	//4/8
//&arr[0] 是 a 的地址,a 的地址 + 1,成了 b 的地址,来来去去算的还是地址

2. 用 strlen 求结果

char arr[] = "abcdef";printf("%d\n", strlen(arr));			//6
//这个数组里 '\f' 的后面就有 '\0' 了printf("%d\n", strlen(arr + 0));		//6
//从首元素地址开始往后找 '\0'printf("%d\n", strlen(*arr));			程序错误
//strlen(*arr) -> strlen ('a') -> strlen(97),把 97 作为地址肯定出问题printf("%d\n", strlen(arr[1]));			程序错误
//strlen(98),将 98 作为地址传给 strlenprintf("%d\n", strlen(&arr));			//6
//&arr 整个数组的地址也是从 'a' 的地址开始的;
//还是传了 'a' 的地址给 strlen,往后找 '\0' 的结果是一样的printf("%d\n", strlen(&arr + 1));		随机值
//从 '\0' 后面开始找 '\0',那什么时候碰到 '\0' 就全看运气了printf("%d\n", strlen(&arr[0] + 1));	//5
//从 'b' 开始往后找 '\0'

题型 3

char* p = "abcdef";//将常量字符串首字符 a 的地址赋给 p

在这里插入图片描述

1. 用 sizeof 求结果

char* p = "abcdef";printf("%zd\n", sizeof(p));			//4/8
//p 是个指针,指针不管指向的是什么东西,指针本身的大小都是 4/8 字节printf("%zd\n", sizeof(p + 1));		//4/8
//让指针 + 1 指向了 'b' ,p + 1 他还是个指针printf("%zd\n", sizeof(*p));		//1
//计算 p 指向的字符 'a' 的大小printf("%zd\n", sizeof(p[0]));		//1
//p[0] <--> *(p + 0) <--> *pprintf("%zd\n", sizeof(&p));		//4/8
//虽然是取出 p 的地址,相当于二级指针,二级指针也是个指针,printf("%zd\n", sizeof(&p + 1));	//4/8
//&p + 1 还是个地址,不过这个地址指向了 '\0' 的后面printf("%zd\n", sizeof(&p[0] + 1));	//4/8
//计算的是 'b' 的地址

2. 用 strlen 求结果

char* p = "abcdef";printf("%d\n", strlen(p));			//6
//p 里存着的是 'a' 的地址,从 'a' 开始往后找 '\0'printf("%d\n", strlen(p + 1));		//5
//p + 1 是 'b' 的地址,从 'b' 开始找 '\0'printf("%d\n", strlen(*p));			程序错误
//*p == 'a',strlen(*p) <--> strlen('a') <--> strlen(97)printf("%d\n", strlen(p[0]));		程序错误
//p[0] <--> *p,和上面情况一样printf("%d\n", strlen(&p));			随机值
//&p 是 p 本身的地址,和常量字符串的地址完全不是一码事,从 p 的地址开始往后随机找 '\0'printf("%d\n", strlen(&p + 1));		随机值
//从 p 之后往后找 '\0',printf("%d\n", strlen(&p[0] + 1));	//5
//&p[0] + 1 指向 'b',从 'b' 开始往后找 '\0'

Ⅲ 二维数组

int a[3][4] = { 0 };					//该二维数组有 12 个元素

在这里插入图片描述

int a[3][4] = { 0 };					//该二维数组有 12 个元素printf("%zd\n", sizeof(a));				//48
//数组名单独放在 sizeof 内部,计算的是整个数组的大小,为 3 * 4 * 4 = 48 字节printf("%zd\n", sizeof(a[0][0]));		//4
//计算第一行第一列的元素的大小,printf("%zd\n", sizeof(a[0]));			//16
//a[0] 表示的是二维数组的第一行,第一行的大小为 4 * 4 = 16 个字节 printf("%zd\n", sizeof(a[0] + 1));		//4/8
//此处的 a[0] 不是单独放在 sizeof 内部,此时 a[0] 表示的是首行首列的地址
//所以 a[0] + 1 <--> &a[0][0] + 1 <--> &a[0][1],这玩意就是个地址printf("%zd\n", sizeof(*(a[0] + 1)));	//4
//*(a[0] + 1) <--> *&a[0][1],* 和 & 相互抵消,就是计算 a[0][1] 的大小printf("%zd\n", sizeof(a + 1));			//4/8
//a 虽然是二维数组的地址,但是并没有单独放在 sizeof 内部,也没取地址;
//此时 a 表示首元素的地址,二维数组的首元素是它的第一行,a 就是第一行的地址;
//a + 1 就是跳过第 1 行,表示的是第二行的地址,是地址就是 4/8 字节printf("%zd\n", sizeof(*(a + 1)));		//16
//对第二行的地址解引用,相当于访问整个第二行,第二行的大小当然是 16 个字节了printf("%zd\n", sizeof(&a[0] + 1));		//4/8
//&a[0] 表示整个第一行的地址,&a[0] + 1 表示第二行的地址,与sizeof(a + 1) 等同printf("%zd\n", sizeof(*(&a[0] + 1)));	//16
//对第二行的地址解引用,访问整个第二行,与 sizeof(*(a + 1)) 等同printf("%zd\n", sizeof(*a));			//16
//a 没有单独放在 sizeof 内部,所以此时的 a 表示的是首元素(第一行)的地址
//*a 相当于访问整个第一行,第一行的大小为 4 * 4 = 16 字节printf("%zd\n", sizeof(a[3]));			//16
//虽然第 4 行不存在,但第 4 行的类型和前 3 行也没什么区别;
//对于 sizeof 来说,只要知道类型就能计算大小,不会真的去访问越界得内容

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

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

相关文章

2023年03月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;和数 给定一个正整数序列&#xff0c;判断其中有多少个数&#xff0c;等于数列中其他两个数的和。 比如&#xff0c;对于数列1 2 3 4, 这个问题的答案就是2, 因为3 2 1, 4 1 3。 时间限制&#xff1a;10000 内存限制&#xff1a;65536 输入 共两行&#x…

TCP-消息队列模型

#include "main.h" fd_win_set setSockets;VOID Server_write_error() {}int cteateserver(HWND hwnd) {WORD wVersionRequested;WSADATA wsaData;int err;/* 使用Windef.h中声明的MAKEWORD&#xff08;低字节、高字节&#xff09;宏 */wVersionRequested MAKEWORD(…

AMBA总线协议(6)——AHB(四):传输细节

一、前言 在之前的文章中&#xff0c;我们已经讲述了AHB传输中的两种情况&#xff0c;基本传输和猝发传输。我们进行一个简单的回顾&#xff0c;首先&#xff0c;开始一次传输之前主机需要向仲裁器申请获得总线的使用权限&#xff0c;然后主机给出地址和控制信号&#xff0c;根…

非计算机科班如何丝滑转码

近年来&#xff0c;很多人想要从其他行业跳槽转入计算机领域。非计算机科班如何丝滑转码&#xff1f; 方向一&#xff1a;如何规划才能实现转码&#xff1f; 对于非计算机科班的人来说&#xff0c;想要在计算机领域实现顺利的转码并不是一件容易的事情&#xff0c;但也并非不…

【JavaEE进阶】SpringMVC

文章目录 一. 简单认识SpringMVC1. 什么是SpringMVC?2. SpringMVC与MVC的关系 二. SpringMVC1. SpringMVC创建和连接2. SpringMVC的简单使用2.1 RequestMapping 注解介绍2.2 RequestMapping支持的请求类型2.3 GetMapping 和 PostMapping 3. 获取参数3.1 传递单个参数3.2 传递对…

【linux】2 Linux编译器-gcc/g++和Linux调试器-gdb

文章目录 一、Linux编译器-gcc/g使用1.1 背景知识1.2 gcc如何完成1.3 函数库1.4 gcc选项 二、linux调试器-gdb使用2.1 背景2.2 开始使用 总结 ヾ(๑╹◡╹)&#xff89;" 人总要为过去的懒惰而付出代价ヾ(๑╹◡╹)&#xff89;" 一、Linux编译器-gcc/g使用 1.1 背景…

/root/.ssh/config line 2: Bad protocol 2 host key algorithms ‘+ssh-rsa‘.

文章目录 1、问题2、查看openssh版本3、解决问题4、重新生成密钥5、查看是否可连接工蜂 1、问题 ssh访问工蜂报错&#xff1a; [rootlocalhost .ssh]# ssh -T gitgit.code.tencent.com /root/.ssh/config line 2: Bad protocol 2 host key algorithms ‘ssh-rsa’. 2、查看o…

升级Qt后VS项目不能使用

错误场景&#xff1a; 如果你的QT卸载了装了新版,那么VS你原来设置的项目就不能跑了. 问题 升级Qt后&#xff36;&#xff33;项目不能使用 跟我一起开始挽救自己的项目 升级Qt后&#xff36;&#xff33;项目不能使用 假如你从5.14.6 升级到 Qt6.2并删除了原来的QT 你在VS里…

Unity 3d角色展示脚本(旋转 平移 缩放)展示界面

不考虑性能 很简陋的一个功能&#xff0c;主要是用于角色渲染的观察用&#xff0c;比simplecontroller要好用一点 using System; using UnityEngine;public class CharacterViewer : MonoBehaviour {public Transform target; // 人物模型的Transformpublic float rotationSpee…

Java网络编程(一)网络基础

概述 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递 网络分类 局域网(LAN) 局域网是一种在小区域内使用的,由多台计算机组成的网络,覆盖范围…

hive-sql

hive-常用SQL汇总 查看数据库 -- 查看所有的数据库 show databases; 使用默认的库 -- 下面的语句可以查看默认的库 use default ;查看某个库下的表 -- 查看所有的表 show tables ; -- 查看包含 stu的表 &#xff0c;这种是通配的方法来查看 show tables like *stu*; 查…

【深入理解jvm读书笔记】jvm如何进行内存分配

jvm如何进行内存分配 内存分配方式内存分配方式的选择并发场景下的内存分配内存空间的初始化构造函数 内存分配方式 指针碰撞空闲列表 指针碰撞法&#xff1a; 假设Java堆中内存是绝对规整的&#xff0c;所有被使用过的内存都被放在一边&#xff0c;空闲的内存被放在另一边&a…

春秋云镜 CVE-2019-16692

春秋云镜 CVE-2019-16692 phpIPAM 1.4 - SQL Injection 靶标介绍 phpIPAM 1.4后台存在SQL Injection。 启动场景 漏洞利用 后台SQL注入&#xff0c;admin/admin888登陆成功。 exp POST /app/admin/routing/edit-bgp-mapping-search.php HTTP/1.1 Host: xxx.com Content-Le…

mysql从传统模式切到GTID模式后启动主从,主从异常报错1236

一 前言 MySQL 的主从复制作为一项高可用特性&#xff0c;用于将主库的数据同步到从库&#xff0c;在维护主从复制数据库集群的时候&#xff0c;作为专职的MySQL DBA&#xff0c;笔者相信大多数人都会遇到“Got fatal error 1236 from master when reading data from binary …

MySQL数据库:内置函数

日期函数 规定&#xff1a;日期&#xff1a;年月日 时间&#xff1a;时分秒 函数名称作用描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date_add(date,interval d_value_type)在date中添加…

jenkins自动部署微服务到docker

1、代码上传到git&#xff1b; 2、jenkins拉取git的代码&#xff0c;maven打包&#xff0c;使用插件生成镜像&#xff0c;自动上传docker&#xff1b; 两个插件&#xff0c;一个打包插件&#xff0c;一个创建镜像上传docker仓库.&#xff08;将dockerfile内容搬到插件配置&…

仿mudou高性能高并发服务器

"这个结局是我的期待&#xff0c;我会一直为你祝福。" 项目实现目标: 仿muduo库One Thread One Loop式主从Reacto模型实现高并发服务器。通过实现高并发服务器组件&#xff0c;简洁快速完成搭建一个高性能服务器。并且&#xff0c;通过组件内提供的不同应⽤层协议⽀…

Kafka基本使用

查看Kafka的进程是否在运行 #命令行终端中运行如下命令 ps -ef | grep kafkafind / -iname kafka-server-start.shcd /usr/local/kafka/bin/#启动kafka ./kafka-server-start.sh -daemon /usr/local/kafka/config/server.propertiesKafka默认使用9092端口提供服务&#xf…

九、Linux下,如何在命令行进入文本编辑页面?

1、文本编辑基础 说到文本编辑页面&#xff0c;那就必须提到vi和vim&#xff0c;两者都是Linux系统中&#xff0c;常用的文本编辑器 2、三种工作模式 3、使用方法 &#xff08;1&#xff09;在进入Linux系统&#xff0c;在输入vim text.txt之后&#xff0c;会进入文本编辑中&…

第8章 CPU后端优化

CPU后端低效&#xff1a;当前端完成取指和译码后&#xff0c;后端发生了过载而不能处理新的指令。TMA将后端bound分为存储和计算bound。 8.1 存储bound 当应用程序执行大量的内存访问并且花费比较长的时间等待内存访问完成时&#xff0c;即被视为存储bound。意味着要改善存储…