经典数组和指针笔试题解析——C语言

【本节内容】

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

2. 指针运算笔试题解析

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

1.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;
}
解答:
//数组名的理解
//数组名一般表示数组首元素的地址
//但是有2个例外:
//1.sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节
//2.&数组名,数组名表示整个数组,取出的数组的地址
//除此之外,所有遇到的数组名都是数组首元素的地址
#include <stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };//数组有四个元素,每个元素是int类型的数据
	printf("%zd\n", sizeof(a));//sizeof(数组名)计算的是整个数组的大小,所以大小是16
	printf("%zd\n", sizeof(a + 0));//a表示首元素的地址,a+0还是首元素的地址,x64环境下地址大小是8个字节,
	                             // x86环境下地址大小是4个字节,所以大小是4/8
	printf("%zd\n", sizeof(*a));//a表示的就是数组首元素的地址,*a就是首元素,大小就是4个字节
	printf("%zd\n", sizeof(a + 1)); //a表示的就是数组首元素的地址,a+1就是第二个元素的地址,x64环境下地址大小是8个字节,
	                             // x86环境下地址大小是4个字节,所以大小是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)-16
	//1.&和*抵消
	//2.&a的类型是数组指针,int(*)[4],*&就是对数组指针解引用访问一个数组的大小,是16个字节
	printf("%zd\n", sizeof(&a + 1));//&a+1是跳过整个数组后的一个地址,是地址,大小就是4/8个字节
	printf("%zd\n", sizeof(&a[0]));//&a[0]是数组第一个元素的地址,大小就是4/8个字节
	printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是数组第一个元素的地址,大小就是4/8个字节
	return 0;
}

1.2 字符数组

代码1:
#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;
}
解答:
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%zd\n", sizeof(arr));//计算整个数组的大小,有6个char类型的字符,所以大小为6个字节
	printf("%zd\n", sizeof(arr + 0));//arr+0是数组首元素的地址,地址的大小是4/8个字节
	printf("%zd\n", sizeof(*arr));//*arr是数组的首元素,这里计算的是首元素的大小 1
	printf("%zd\n", sizeof(arr[1]));//数组下标为一的元素的大小
	printf("%zd\n", sizeof(&arr));//&arr - 是数组的地址,数组的地址也是地址,是地址就是4/8个字节
	printf("%zd\n", sizeof(&arr + 1));//&arr+1,跳过整个数组,指向了数组的后边,4/8
	printf("%zd\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8

	return 0;
}
 代码2:
#include <stdio.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; 
}
解答:
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//随机值
	printf("%d\n", strlen(arr + 0));//随机值
	                     //'a'-97
	//printf("%d\n", strlen(*arr));//err
	//                   //'b'-98
	//printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//随机值
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//随机值

	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>
#include <string.h>
int main()
{
	char arr[] = "abcdef";

	printf("%zd\n", sizeof(arr));//计算字符串大小(包括\0),长度为7
	printf("%zd\n", sizeof(arr + 0));//arr+0是数组首元素的地址,地址的大小是4/8个字节
	printf("%zd\n", sizeof(*arr));//*arr是数组的首元素,这里计算的是首元素的大小 1
	printf("%zd\n", sizeof(arr[1]));//1
	printf("%zd\n", sizeof(&arr));//&arr - 是数组的地址,数组的地址也是地址,是地址就是4/8个字节
	printf("%zd\n", sizeof(&arr + 1));//&arr+1,跳过整个数组,指向了数组的后边,4/8
	printf("%zd\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8

	return 0;
}
代码4:
#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";

	printf("%zd\n", strlen(arr));//arr也是数组首元素的地址 6
	printf("%zd\n", strlen(arr + 0));//arr + 0是数组首元素的地址,6
	printf("%zd\n", strlen(*arr));//?传递是'a'-97,//err
	printf("%zd\n", strlen(arr[1]));//?'b'-98//err
	printf("%zd\n", strlen(&arr));//6, &arr虽然是数组的地址,但是也是指向数组的起始位置
	printf("%zd\n", strlen(&arr + 1));//随机值
	printf("%zd\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 - 5

	return 0;
}
代码5:
#include <stdio.h>
int main()
{
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));
return 0;
}
解答:
#include <stdio.h>
int main()
{
	char* p = "abcdef";
	printf("%zd\n", sizeof(p));//4/8 计算的指针变量的大小
	printf("%zd\n", sizeof(p + 1));//p + 1是'b'的地址,是地址大小就是4/8个字节
	printf("%zd\n", sizeof(*p));//*p就是'a',大小是1个字节
	printf("%zd\n", sizeof(p[0]));//p[0]--> *(p+0) - *p //1字节
	printf("%zd\n", sizeof(&p));//&p也是地址,是指针变量p的地址,大小也是4/8个字节
	printf("%zd\n", sizeof(&p + 1));//&p + 1是指向p指针变量后面的空间,也是地址,是4/8个字节
	printf("%zd\n", sizeof(&p[0] + 1));//&p[0]+1是'b'的地址,是地址就是4/8个字节

	return 0;
}
代码6:
#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("%zd\n", strlen(p));//6
	printf("%zd\n", strlen(p + 1));//5
	printf("%zd\n", strlen(*p));//err
	printf("%zd\n", strlen(p[0]));//p[0]--*(p+0)-->*p //err
	printf("%zd\n", strlen(&p));//随机值
	printf("%zd\n", strlen(&p + 1));//随机值
	printf("%zd\n", strlen(&p[0] + 1));//5

	return 0;
}

1.3 二维数组

代码:
#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 };
	printf("%zd\n", sizeof(a));//12*4 = 48个字节,数组名单独放在sizeof内部
	printf("%zd\n", sizeof(a[0][0]));//4
	printf("%zd\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名,数组名单独放在sizeof内部了
	//计算的是第一行的大小,单位是字节,16个字节

	printf("%zd\n", sizeof(a[0] + 1));//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是数组收元素的地址,应该是第一行的地址,a+1是第二行的地址
	//大小也是4/8 个字节
	printf("%zd\n", sizeof(*(a + 1)));//*(a + 1) ==> a[1] - 第二行的数组名,单独放在sizeof内部,计算的是第二行的大小
	//16个字节
	printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0]+1就是第二行的地址,4/8
	printf("%zd\n", sizeof(*(&a[0] + 1)));//访问的是第二行,计算的是第二行的大小,16个字节
	//int(*p)[4] = &a[0] + 1;
	//
	printf("%zd\n", sizeof(*a));//这里的a是第一行的地址,*a就是第一行,sizeof(*a)计算的是第一行的大小-16
	//*a --> *(a+0) --> a[0]
	printf("%zd\n", sizeof(a[3]));//这里不存在越界
	//因为sizeof内部的表达式不会真实计算的
	//计算的是第四行的大小-16

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

2. 指针运算笔试题解析

2.1 题目1:

#include <stdio.h>
int main()
{
 int a[5] = { 1, 2, 3, 4, 5 };
 int *ptr = (int *)(&a + 1);
 printf( "%d,%d", *(a + 1), *(ptr - 1));
 return 0;
}
//程序的结果是什么?
运行结果:

解析:

2.2 题目2  

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结果是啥?
struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0;
}
运行结果:

解析:
//在X86环境下
//假设结构体的大小是20个字节
//程序输出的结果是啥?
#include <stdio.h>
struct Test
{
    int Num;
    char* pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}* p = (struct Test*)0x100000;
//
//指针+整数
//
int main()
{
    printf("%x\n", p + 0x1); //0x100000+20 == 0x100014
    printf("%x\n", (unsigned long)p + 0x1);//0x100000+1 == 0x100001
    printf("%x\n", (unsigned int*)p + 0x1);//0x100000+1 == 0x100004
    return 0;
}

2.3 题目3

#include <stdio.h>
int main()
{
 int a[3][2] = { (0, 1), (2, 3), (4, 5) };
 int *p;
 p = a[0];
 printf( "%d", p[0]);
 return 0;
}
运行结果:

解析:

2.4 题目4

//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
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;
}
运行结果:

解析: 

2.5 题目5 

#include <stdio.h>
int main()
{
 int aa[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;
}
运行结果: 

解析:

2.6 题目6

#include <stdio.h>
int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}
运行结果:

解析:

PS:看到这里了,码字不易,给个一键三连鼓励一下吧!有不足或者错误之处欢迎在评论区指出!  

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

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

相关文章

如何保证Redis和数据库数据一致性

缓存可以提升性能&#xff0c;减轻数据库压力&#xff0c;在获取这部分好处的同时&#xff0c;它却带来了一些新的问题&#xff0c;缓存和数据库之间的数据一致性问题。 想必大家在工作中只要用了咱们缓存势必就会遇到过此类问题 首先我们来看看一致性&#xff1a; 强一致性…

Datawhale【Sora原理与技术实战】| 学习笔记3

目录 一. 训练 Sora 模型二. 数据预处理三. 视频 VQVAE四. Diffusion Transformer 一. 训练 Sora 模型 Open-Sora 在下图中总结了 Sora 可能使用的训练流程&#xff1a; 链路: 二. 数据预处理 目前主流 LLM 框架缺乏针对 video 数据 统一便捷的管理和处理能力&#xff0c;…

第十四届蓝桥杯省赛真题 Java 研究生 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 特殊日期试题 B: 与或异或试题 C: 棋盘试题 D: 子矩阵试题 E : \mathrm{E}: E: 互质数的个数试题 F: 小蓝的旅行计划试题 G: 奇怪的数试题 H: 太阳试题 I: 高塔试题 J \mathrm{J} J : 反异或 01 串 发现宝藏 前些天发现了一个巨牛的人…

InstantID Zero-shot Identity-Preserving Generation in Seconds

InstantID: Zero-shot Identity-Preserving Generation in Seconds TL; DR&#xff1a;InstantID IP-Adapter (Face) ControlNet&#xff0c;实现了具有较高保真度的人脸 ID 生成。 方法 InstantID 想做到的事情是&#xff1a;给定一张参考人脸 ID 图片&#xff0c;生成该…

6. 面向对象(重点)

1 面向对象 1.1 了解对象 学习面向对象编程都先我们需要先思考三个问题: 1.1.1 面向对象的好处? Java作者詹姆斯.高斯林说过**万物皆对象**汽车的数据可以找汽车对象处理手机数据可以找手机对象处理学生的数据可以找学生对象处理使用面向对象编程符合人类思维习惯, 就好比…

Java的编程之旅41——字符流

目录 1.字符流的简介 2.字符的编码与解码 3.字符流读写操作 1.字符流写入 2.字符流复制文件 4.FileWriter&FileReader 5.缓冲区高效读写 6.序列化与反序列化 1.字符流的简介 在Java中&#xff0c;字符流是用于处理字符数据的输入输出流。它是以字符为单位进行处理&a…

户外大屏:六个必备的户外大屏推广工具助你脱颖而出-华媒舍

1. 大屏幕LED显示屏 大屏幕LED显示屏是一种常见而有效的户外推广工具。它采用LED背光源和高分辨率显示屏&#xff0c;能够在户外环境中展示鲜艳丰富的图像和视频内容。这种显示屏广泛应用于广场、商业街、体育场馆等公共场所&#xff0c;成为吸引人们目光的重要工具。 大屏幕…

AIOps探索 | 国外知名厂商根因分析实践分享新方法探索

文章来源于公众号--布博士&#xff08;擎创科技资深产品专家&#xff09; 哈喽&#xff0c;大家好~转眼又到我们分享干货环节了&#xff0c;上一篇AIOps干货后台收到不少反馈&#xff0c;总体来说效果还不错&#xff0c;感谢大家喜欢&#xff0c;后续楼主会定期更新AIOps相关干…

如何使用“ubuntu移动文件、复制文件到其他文件夹“?

一、移动文件到其他文件夹命令 mv node_exporter-1.5.0.linux-amd64.tar.gz /usr/local/etc/prometheus 二、复制文件到其他文件夹命令 cp node_exporter-1.5.0.linux-amd64.tar.gz /home/master

一个八年工作经验老程序员的分享

作为一个 Java 程序员&#xff0c;我在这个行业中工作了多年。在这个过程中&#xff0c;我经历了许多挑战和机遇&#xff0c;也学到了很多宝贵的经验和教训。在这篇文章中&#xff0c;我想分享一些我的感想和思考&#xff0c;希望能够对其他 Java 程序员有所帮助。 一、技术的…

【linux】进程管理:进程控制块、进程号、fork创建进程、特殊进程及exec函数族解析

一、进程的概述 可执行程序运行起来后&#xff08;没有结束之前)&#xff0c;它就成为了一个进程。程序是存放在存储介质上的一个可执行文件&#xff0c;而进程是程序执行的过程。进程的状态是变化的&#xff0c;其包括进程的创建、调度和消亡。程序是静态的&#xff0c;进程是…

基于蓝牙技术的资产管理

随着物联网技术的不断发展&#xff0c;蓝牙技术已经成为了许多领域中不可或缺的一部分。在资产管理领域&#xff0c;基于蓝牙技术的资产定位管理方案正在逐渐普及&#xff0c;为企业提供了更加高效、精准的资产管理方式。本文将从蓝牙技术的原理、资产定位管理的需求、系统架构…

全栈之路-新坑就绪-星野空间

感觉自己的技术栈一直没有形成一个很好的闭环 开新坑&#xff0c;准备把自己的技术栈链路打通&#xff0c; Don‘t think too much&#xff0c; just act&#xff01;[得意]

python retry装饰器使用

第一个例子 import time from functools import wraps from typing import Callable, Any from time import sleepdef retry(retries: int 3, delay: float 1) -> Callable:"""Attempt to call a function, if it fails, try again with a specified dela…

基于单片机的恒压供水控制器设计

摘 要 随着我国现代化的进程不断加快&#xff0c;城市居民生活水平不断提高&#xff0c;随之而来的是房屋的翻新和重建&#xff0c;但建筑层数的不断增高&#xff0c;使得供水所需压力不断提高&#xff0c;若建筑设计时对压力判断不足&#xff0c;会导致供水时无法供应到高楼层…

NO9 蓝桥杯单片机之串口通信的使用

1 基本概念 简单来说&#xff0c;串口通信是一种按位&#xff08;bit&#xff09;传输数据的通信方式。 其他一些知识就直接贴图吧&#xff08;单工&#xff0c;半双工这些学过通信的同学应该都知道&#xff0c;可以上网查询一下具体概念。&#xff09; 来源还是&#xff1a;…

第16届大广赛XPPen都有哪些参赛命题

截至到发文时间&#xff0c;2024年3月14日&#xff0c;第16届大广赛已经累计公布了6个品牌命题&#xff0c;本文就给大家介绍一下XPPen命题的详细细节。 XPPen为汉王友基旗下全球知名数字艺术创新品牌&#xff0c;专注消费级用户创作需求&#xff0c;品牌产品覆盖全球160多个国…

一张图搞清楚wait、sleep、join、yield四者区别,面试官直接被征服!

写在开头 在线程的生命周期中&#xff0c;不同状态之间切换时&#xff0c;可以通过调用sleep()、wait()、join()、yield(&#xff09;等方法进行线程状态控制&#xff0c;针对这一部分知识点&#xff0c;面试官们也会做做文章&#xff0c;比如问你这些方法的作用以及之间的区别…

Linux中mysql的安装、远程访问、基础操作、文件导入

Linux中mysql的安装、远程访问、基础操作、文件导入 cheet card1. 安装1. 使用root账号安装mysql 2. 启动mysql并创建root、管理员两个账号3. 基础操作3.1 数据库的查看、创建、修改、删除3.2 mysql的数据类型3.3 数据表的基本操作3.4 数据表结构的修改3.5 表中数据的增、删、改…

Kotlin编程权威指南学习知识点预览

一、变量、常量和类型&#xff1a; 变量、常量以及 Kotlin 基本数据类型。变量和常量在 应用程序中可用来储值和传递数据。类型则用来描述常量或变量中保存的是什么样的数据。 1、声明变量: // 变量定义关键字 —— 变量名 —— 类型定义 —— 赋值运算符 —— 赋值var na…