【c语言】指针和数组笔试题

2023-09-20 17:55:21

1.指针和数组笔试题解析

一维数组

	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//a单独放在sizeof内表示求整个数组的字节-----16
	printf("%d\n", sizeof(a + 0));//a不是单独放在sizeof内部,表明是首元素的地址,地址占4/8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*a));//a为首元素的地址,*a就是数组第一个元素,大小为4个字节
	printf("%d\n", sizeof(a + 1));//a不是单独放在sizeof内,a表示首元素地址,+1为第二个元素地址,地址占4/8个字节,32位机器占4个字节
	printf("%d\n", sizeof(a[1]));//a[1]为第二个元素,大小为int 4个字节
	printf("%d\n", sizeof(&a));//&a表示整个数组的地址,是地址就占4/8个字节,32位机器占四个字节
	printf("%d\n", sizeof(*&a));//取地址解引用相当于sizeof(a),a单独放在sizeof内表示求整个数组的字节-----16
	printf("%d\n", sizeof(&a + 1));//&a为取出整个数组的地址,+1,直接跳过整个数组,指向数组的尾,但是还是地址,地址就占4/8个字节
	printf("%d\n", sizeof(&a[0]));//&a[0]为第一个元素地址,地址占4/8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]为第一个元素地址,+1为第二个元素地址,地址占4/8个字节。

字符数组

char arr[] = { 'a','b','c','d','e','f' }; 
	printf("%d\n", sizeof(arr));//arr单独放在sizeof内表示求整个数组的字节-----6
	printf("%d\n", sizeof(arr + 0));//arr不是单独放在sizeof内部,+0相当于第一个元素的地址,地址占4/8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*arr));//arr不是单独放在sizeof内部,arr为首地址,解引用拿到第一个元素,占一个字节
	printf("%d\n", sizeof(arr[1]));//第二个元素,占一个字节
	printf("%d\n", sizeof(&arr));//整个数组的地址,地址占4/8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&arr + 1)); //&arr为取出整个数组的地址, + 1,直接跳过整个数组,指向数组的尾,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]第一个元素的地址,+1为第二个元素地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", strlen(arr));//从arr地址开始找'\0',--------随机数(字符数组没带反斜杠0)
	printf("%d\n", strlen(arr + 0));//arr+0为第一个元素地址开始找'\0'-------随机数(字符数组没带反斜杠0)
	printf("%d\n", strlen(*arr));//arr为首元素地址,对其解引用拿到的是第一个元素,strlen把他当做地址往后找'\0'-------奔溃
	printf("%d\n", strlen(arr[1]));//arr[1]为第二个元素,strlen把他当做地址往后找'\0'-------奔溃
	printf("%d\n", strlen(&arr));//&arr为整个数组的地址,strlen把他当做地址往后找'\0'-------随机数
	printf("%d\n", strlen(&arr + 1)); //&arr为整个数组的地址,+1跳过数组,跳到这个地址往后找'\0'-------随机数
	printf("%d\n", strlen(&arr[0] + 1));//&arr[0]为第一个元素地址,然后+1就是第2个元素的地址开始找'\0'--------随机数(字符数组没带反斜杠0)

字符串数组

char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//arr单独放在sizeof内表示求整个数组的字节-----7(字符串数组末尾有个反斜杠0)
	printf("%d\n", sizeof(arr + 0));//arr没单独放在内部,+0,表示第一个元素地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*arr));//arr没单独放在内部,arr为元素首地址,*arr拿到第一个元素,1个字节
	printf("%d\n", sizeof(arr[1]));//arr[1]为第二个元素,为1个字节
	printf("%d\n", sizeof(&arr));//&arr为整个数组的地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&arr + 1));//&arr为整个数组的地址,+1跳过这个数组,的地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]为第一个元素地址,+1为第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节






	printf("%d\n", strlen(arr));//arr为首元素地址,从arr地址往后开始找'\0'-------6
	printf("%d\n", strlen(arr + 0));//arr+0为首元素地址,从arr地址往后开始找'\0'-------6
	printf("%d\n", strlen(*arr));//arr为首元素地址,解引用为第一个元素,把第一个元素当地址往后找反斜杠0------奔溃
	printf("%d\n", strlen(arr[1]));//arr[1]为第二个元素,把第二个元素当地址往后找反斜杠0------奔溃
	printf("%d\n", strlen(&arr));//&arr为整个数组的地址,strlen把他当做地址往后找'\0'-------6
	printf("%d\n", strlen(&arr + 1));//&arr为整个数组的地址, + 1跳过数组,跳到这个地址往后找'\0'------ - 随机数
	printf("%d\n", strlen(&arr[0] + 1));//&arr[0]为第一个元素地址,然后 + 1就是第2个元素的地址开始找'\0'------5

指针保存字符串数组首地址

	char* p = "abcdef";
	printf("%d\n", sizeof(p));//p保存的是字符串首元素的地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(p + 1)); //p保存的是字符串首元素的地址,+1为第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*p)); //p保存的是字符串首元素的地址,对他解引用得到的是第一个元素,占一个字节
	printf("%d\n", sizeof(p[0]));//p[0]相当于*(p+0),第一个元素占一个字节
	printf("%d\n", sizeof(&p)); //p指针的地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&p + 1)); //p指针的地址+1,还是地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(&p[0] + 1));//p[0]相当于第一个元素,&p[0]相当于第一个元素地址,&p[0] + 1为第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节

	printf("%d\n", strlen(p));//p保存的是字符串首元素的地址,从首元素地址开始往后找反斜杠0--------6
	printf("%d\n", strlen(p + 1));//p保存的是字符串首元素的地址,+1为第二个元素地址开始往后找反斜杠0--------5
	printf("%d\n", strlen(*p));//p保存的是字符串首元素的地址,解引用为第一个元素,strlen把他当地址开始往后找反斜杠0------奔溃
	printf("%d\n", strlen(p[0]));//p[0]为首元素,将a的ascll码值当地址开始往后找反斜杠0------奔溃
	printf("%d\n", strlen(&p));//p指针的地址,开始往后找反斜杠0-----随机值
	printf("%d\n", strlen(&p + 1)); //p指针的地址+1,开始往后找反斜杠0-----随机值
	printf("%d\n", strlen(&p[0] + 1));//p[0]相当于第一个元素,&p[0]相当于第一个元素地址,&p[0] + 1为第二个元素地址开始往后找反斜杠0-------5

二维数组

	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//a单独放在sizeof内表示求整个数组的字节------3*4*4=48
	printf("%d\n", sizeof(a[0][0]));//第一个元素,大小为4个字节
	printf("%d\n", sizeof(a[0]));//a[0]相当于数组名---*(a+0)---*a,如果是一维数组a表示首元素的地址,二维数组a表示第一行数组的地址,相当于把第一行整个数组放在sizeof内部,*a表示第一行元素,4*4=16;
	printf("%d\n", sizeof(a[0] + 1));//a[0]相当于数组名,但是没有单独放在sizeof内部,相当于第一行第一个元素地址,+1为第一行第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*(a[0] + 1)));//上一个说(a[0] + 1)这个是第二个元素的地址,对其解引用得到的是第二个元素,为4个字节
	printf("%d\n", sizeof(a + 1));//a没有单独放在sizeof内,表示第一行的地址,+1表示第二行的地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*(a + 1)));//上一个说a + 1为第二行的地址,对其解引用得到第二行,4*4=16;
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]为第一行的地址,&a[0] + 1为第二行的地址,地址就占4 / 8个字节,32位机器占4个字节
	printf("%d\n", sizeof(*(&a[0] + 1)));//第二行的地址解引用得到第二行,4*4=16;
	printf("%d\n", sizeof(*a));//a没有单独放在sizeof内,a表示第一行的地址,*a得到是第一行,4*4=16;
	printf("%d\n", sizeof(a[3]));//sizeof(a[3])直接会被替换成sizeof(a[0]),不会访问a[3]的地址,不会越界访问--16

2.总结

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

3.指针笔试题

笔试题1:

int main()
{
    inta[5] = { 1, 2, 3, 4, 5 };
    int*ptr= (int*)(&a+1);
    printf( "%d,%d", *(a+1), *(ptr-1));    return0;
}
//程序的结果是什么?

分析:
在这里插入图片描述
在这里插入图片描述

笔试题2

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。如下表表达式的值分别为多少?
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

分析:1. p为结构体指针,+1相当于跳过一个结构体大小,这里告知结构体的大小是20个字节,p + 0x1按16进制打印出来是0x100014
2. p转化为无符号 长整型,并非指针,+1,就是+1,0x100001
3. p转化为无符号整型类型指针+1跳过四个字节。0x100004
由于以%p打印,第一个00100014,第二个00100001,第三个00100004
在这里插入图片描述
他这里的p的值为0x000000

笔试题3:

int main()
{
    inta[4] = { 1, 2, 3, 4 };
    int*ptr1= (int*)(&a+1);
    int*ptr2= (int*)((int)a+1);
    printf( "%x,%x", ptr1[-1], *ptr2);    return0;
}

分析:在这里插入图片描述
在这里插入图片描述

笔试题4:

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) }; 
	int* p;
	p = a[0];
	printf("%d", p[0]); 
	return 0;
}

分析:==注意里面不是这种{}==所以是逗号表达式在这里插入图片描述
在这里插入图片描述

笔试题5:

int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]); 
	return 0;
}

分析:
在这里插入图片描述
在这里插入图片描述

笔试题6:

int main()
{
    intaa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };    
    int*ptr1= (int*)(&aa+1);
    int*ptr2= (int*)(*(aa+1));
    printf( "%d,%d", *(ptr1-1), *(ptr2-1));
    return 0;
}

分析:在这里插入图片描述

在这里插入图片描述

笔试题7:

int main() 
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

分析

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

笔试题8:

int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

分析

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

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

更多推荐

【Docker系列】Docker-核心概念/常用命令与项目部署实践

写在前面Docker是一种开源的容器化技术,它允许开发者将应用程序及其依赖项打包到一个轻量级、可移植的容器中,从而实现快速部署和高效运行。Docker的核心概念包括镜像、容器、仓库等。本文将详细介绍Docker的基本概念、安装方法以及常用命令。一、Docker基本概念介绍3个基础概念:镜像(Image)容器(Conta

JVM——2.JVM的内存结构

这篇文章来讲一下JVM中的重点之一——JVM的内存结构目录1.概述2.程序计数器3.虚拟机栈3.1栈的介绍3.2栈的相关问题3.3栈内存溢出问题3.4线程运行诊断4.本地方法栈5.堆5.1堆的概述5.2堆内存溢出问题5.3堆内存诊断6.方法区6.1方法区的概述6.2方法区的内存溢出问题7.运行时常量池8.直接内存8.1

在 Swift 中使用 async let 并发运行后台任务

文章目录前言长期运行的任务阻塞了UI使用async/await在后台执行任务在后台执行多个任务使用"asynclet"下载多个文件结论前言Async/await语法是在Swift5.5引入的,在WWDC2021中的Meetasync/awaitinSwift对齐进行了介绍。它是编写异步代码的一种更可读的方式,比调度队列

基于yolov5的交通标志牌的目标检测研究设计——思路及概念

有需要项目的可以私信博主!!!!!一、选题的目的、意义及研究现状(1)选题的目的和意义随着人们对道路安全性的重视和城市交通量的不断增加,交通标志牌作为道路交通安全的重要组成部分之一,扮演着十分重要的角色。然而,交通标志牌的数量庞大、种类繁多,人工巡视的方式存在效率低、漏检率高等问题,对道路交通的安全性带来了一定的隐患。

Vue模板语法(下)

一.事件处理器什么是事件处理器建立一个HTML编写事件处理器测试结果二.表单的综合案例什么是表单综合案例建立一个HTML来编写表单案例测试结果三.局部组件什么是组件通信自定义组件测试结果组件通信-父传子测试结果组件通信-子传父测试结果一.事件处理器什么是事件处理器事件处理器是一种用于响应和处理用户交互事件的机制。在We

zookeeper最基础教程

文章目录一、简介1、工作机制2、特点3、数据结构4、应用场景5、选举机制二、软件安装1、单机版安装2、集群安装3、配置参数解读(zoo.cfg)4、ZK集群启动脚本三、命令行操作1、语法2、使用3、节点相关4、监听器原理5、节点删除与查看三、写数据流程一、简介1、工作机制官方地址:https://zookeeper.a

SpringMVC之JSON数据返回与异常处理机制---全方面讲解

一,JSON数据返回的理解在SpringMVC中,当需要将数据以JSON格式返回给客户端时,可以使用@ResponseBody注解或@RestController注解将Controller方法的返回值直接转化为JSON格式并返回。这使得开发者可以方便地将Java对象转换为JSON,并通过HTTP响应返回给客户端。Spr

TCP协议

文章目录TCP协议1.TCP协议段格式(1)2个核心问题(解包与分用)(2)TCP的可靠性2.确认应答(ACK)机制3.16位窗口大小4.6位标志位(1)ACK(2)SYN(3)FIN(4)PSH(5)RST(6)URG5.超时重传机制6.连接管理机制6.0TCP协议通讯流程6.1三次握手(1)前置问题(2)细节问题(

面试题三:请你谈一谈Vue中的filter功能的实现

Vue中过滤器(filter)的使用我们想一下有methods为什么要有filter的存在呢,因为filter的实现效率比methods要高的多。看一下官方定义:Vue.js允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和v-bind表达式(后者从2.1.0+开始支持)。过滤器应

Vue3 学习-组件通讯(二)

文章目录前言一、props通信二、自定义事件(emit)三、全局事件总线(EventBus)四、v-model五、userAttrs六、ref和$parent七、Provide与Inject八、pinia九、slot插槽总结前言本文主要记录Vue3的九种组件通信方式一、props通信子组件需要用defineProps方

springboot日志配置(logback+slf4j配置)

1.为什么要配置日志故障排查和问题分析:日志记录允许开发人员和运维人员在系统发生问题或故障时追踪问题的根本原因。通过查看日志文件,他们可以了解系统在特定时间点发生了什么事情,从而更容易定位和解决问题。性能监控和优化:日志记录可以帮助监控应用程序和系统的性能。通过分析日志数据,你可以识别性能瓶颈和瓶颈的位置,从而采取相应

热文推荐