重生之我在异世界学编程之C语言:深入指针篇(下)

news2025/1/14 18:02:23

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

目录

  • 题集
    • (1)指针笔试题1
    • (2)指针笔试题2
    • (3)指针笔试题3
    • (4)指针笔试题4
    • (5)指针笔试题5
    • (6)指针笔试题6
    • (7)指针笔试题7
    • (8)指针笔试题8
    • (9)指针笔试题9
  • 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

题集

(1)指针笔试题1

判断代码运行结果

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

	printf("%d\n", strlen(arr));   
	printf("%d\n", strlen(arr + 0));    
	printf("%d", strlen (*arr));     
    printf("%d", strlen(arr[1]));     
	printf("%d\n", strlen (&arr));     
	printf("%d\n", strlen (&arr + 1));    
	printf("%d\n", strlen (&arr[0] + 1));    
	
	return 0;
}

建议思考写下自己的答案再看后文进行核对与理解

答案解析
5sizeof()内仅有arr(数组名), arr代表整个数组,所以sizeof计算的是整个数组的大小——5(单位:字节)
4/8除了仅有arr&arrarr代表的是整个数组,其他arr代表的都是数组首元素的地址,地址的大小就是4/8(至于4/8取决于32位机器或64位机器)
1*arr就是数组首元素'a'(int),大小为1
1arr[1] == *(arr + 1),就是数组的第二个元素,大小为1
4/8&arr中的arr代表的是整个数组,所以&arr代表的是整个数组的地址,大小就是4/8
4/8&arr + 1中的arr代表的是整个数组,所以&arr + 1代表的是整个数组后的和数组一样大小的连续元素的地址,大小就是4/8
4/8第二个元素的地址
4strlen(arr)arr代表的是数组首元素的地址,所以strlen()从数组首元素开始数到至’\0’,结果就为:4
4strlen(arr+0)arr代表的是数组首元素的地址,所以strlen()从数组首元素开始数至’\0’,结果就为:4
非法访问*arr表示数组首元素,而strlen()要的是地址,所以非法访问
非法访问同上
4&arr取出了整个数组的地址,就数整个数组,结果就为:4
随机&arr + 1 就跳过了整个数组,不知道什么时候出现’\0’,也不知道任何元素的信息,所以打印的是个随机数
3&arr[0] + 1 就跳过了首元素,结果就为:3

考察:一维数组的数组名——特殊与一般
涉及:一维数组,strlen(),sizeof()


(2)指针笔试题2

判断代码运行结果

#include<stdio.h>
#include<string.h>
int main() {
	char* p = "abcd";
	//这个代码的意思:把首元素的地址(a的地址)放到指针变量p中
	//p就相当于一般的arr(除了两种特殊情况除外)(首元素的地址)
	printf("%d\n", sizeof(p)); //地址的大小就是4/8(字节)(至于4/8取决于32位机器或64位机器)
	printf("%d\n", sizeof(p + 0 ));   //同上
	printf("%d\n", sizeof (*p));   //*p就是数组首元素'a'(char),大小为1(字节)
	printf("%d\n", sizeof(p[1]));   //p[1] == *(p + 1),就是数组的第二个元素,大小为1(字节)
	printf("%d\n", sizeof(&p));    //&p中的p代表的是数组首元素的地址,所以&p代表的是存储指针变量p的地址,大小就是4/8
	printf("%d\n", sizeof(&p + 1));   //&p + 1中的p代表的是数组首元素,所以&p + 1代表的是存储指针变量p的地址处后一位的地址,大小就是4/8
	printf("%d\n", sizeof(&p[0] + 1));   //b的地址,大小就是4/8

	printf("%d\n", strlen(p));   //strlen(p)中p代表的是数组首元素的地址,所以strlen函数从数组首元素开始数至'\0',结果就为:4
	printf("%d\n", strlen(p + 0));    //strlen(p + 0)中p代表的是数组首元素的地址,所以strlen函数从数组首元素开始数至'\0',结果就为:4
	//printf("%d", strlen (*p));     //*p表示数组首元素,而strlen函数要的是地址,所以非法访问
	//printf("%d", strlen(p[1]));     //同上
	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] + 1 就跳过了首元素,结果就为:3

	return 0;
}

考察:字符指针——把首元素的地址(a的地址)放到指针变量p中
涉及:字符指针,strlen()


(3)指针笔试题3

判断代码运行结果


#include<stdio.h>
struct test {
	int Num;
	char* pcname;
	short sDate;
	char cha[2];
	short sBa[4];
}* p;
//假设 * p = 0x00000000;
//已知结构体变量test的大小为20字节;
int main() {
	printf("%p\n", p + 1);
	//指针加1跳过整个指针权限的内容(步长)(解引用权限),所以这里跳过了整个结构体变量,也就是20个字节,结果用十六进制表示就是00000014
	printf("%u\n", (unsigned long)p + 1);
	//先把结构体指针变量p强转成无符号长整型变量,再加1就是让一个整型变量加1,结果就是加1,用十进制表示就是1
	printf("%p\n", (unsigned int*)p + 1);
	//先把结构体指针变量p强转成整型指针变量,再加1就是让一个整型指针变量加1,指针加1跳过整个权限的内容,所以这里跳过了整个整型变量,也就是4个字节,结果用十六进制表示就是00000004
}

考察:指针加1的意义,是跳过一个步长的地址
涉及:结构体指针,基本指针


(4)指针笔试题4

判断代码运行结果

//x86,小端
#include<stdio.h>
   int main() {
	int a[4] = { 1, 2, 3, 4 };
	int* p = (int*)(&a + 1);
	int* p1 = (int*)((int)(a + 1) + 1);   //如果我们定义一个:int* pa = a;   则a + 1就等价于*(pa + 1)
	printf("%x\n", p[-1]);  
	//1.p[-1] == *(p - 1),因为p的类型为int*,所以p-1就是向前挪动一个整型(4个字节)的长度,指向了第4个元素的第一个字节的最左端
	//2.再进行解引用,根据p的访问权限可知从当前位置向后访问一个整型(4个字节),就得到了数组的第4个元素——4
	//3.又因为%x是用来打印十六位进制数且会去掉前面的0,所以打印就是4
	printf("%x\n", * p1); 
	//1.a + 1: 
	             //低地址                                       高地址//低地址                                       高地址                                                         
	             //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00    //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
	   //地址设为:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f    //00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f    
	   //指针位置:pa                                              -->              pa    
	//2.(int)(a + 1): 把 地址04 强转成一个大小等于 04 的整型数据
	//3.(int)(a + 1) + 1:一个整型数据加1,就是数值加1,此时((int)(a + 1) + 1)就得到了一个数值大小为 05 的整型数据
	//4.((int*)((int)(a + 1) + 1)):把数值大小为 05 的整型数据强转为 地址05
	//5.int* p1 = (int*)((int)(a + 1) + 1):把上面得到的 05的地址 赋给 类型为int*的 整形指针变量p1
	//6.printf("%x\n", * p1):再进行解引用,根据p的访问权限可知从当前位置向后访问一个整型(4个字节),就得到了00 00 00 03(小端存储),转换为03 00 00  00(原值)(小端存储是以字节为单位的)
	//7.又因为%x是用来打印十六位进制数且会去掉前面的0,所以打印就是3000000
	return 0;
}

考察并涉及:小端存储,%x的作用,指针运算


(5)指针笔试题5

判断代码运行结果

#include<stdio.h>
int main() {
	int arr[] = { 1, 2, 3, 4 };
	int* p = (int*)(&arr + 1);
	printf("%d\n", *(p - 1));
	//没什么好讲的
	printf("%d\n", *(arr + 1));
	//同上
	return 0;
}

考察并涉及:一维数组数组名


(6)指针笔试题6

判断代码运行结果

#include<stdio.h>
int main() {
	int arr[2][3] = { (1, 2), (3, 4), (5, 6)};
	//逗号表达式的值就是','右边的表达式的结果(但要注意:','左边的表达式也会执行,且是先执行的)
	//所以该二维数组的元素为://2 4
	                          //6 0
	                          //0 0
	int* p;
	p = arr[0];
	printf("%d\n", p[1]);
	//两种理解p[1]的方法
	//1.用数组的格式理解:p = arr[0],则p[1] = arr[0][1] = 4;
	//2.用数组的本质理解:arr[0]作为二维数组的第一行的数组元素的数组名,代表的是数组第一行的首元素的地址,即——&arr[0][0],
	                    //p[1] == *(p + 1) == *(&arr[0][0] + 1) == 4
	return 0;
}

考查并涉及:指针与二维数组的关系和逗号表达式的作用


(7)指针笔试题7

判断代码运行结果

#include<stdio.h>
int main() {
	int arr[5][5];
	//数组元素:|0 0 0 0 0 | 0 0 0 0 0 | 0 0 0 0 0 | 0 0 0 0 0 | 0 0 0 0 0 | 
	//             arr[0]      arr[1]     arr[2]      arr[3]      arr[4]
	//地址设为:|0 1 2 3 4 | 5 6 7 8 9 | a b c d e | f 0 1 2 3 | 4 5 6 7 8 |
	int(*p)[4] = (int(*)[4])arr;
	//arr作为二维数组的数组名,类型为:int(*)[5],与数组指针变量p(类型为:int(*)[4])类型基本一致,所以强转之后可以和数组名一样理解
	printf("%p,%d\n", &p[4][2] - &arr[4][2], &p[4][2] - &arr[4][2]);
	//以p为二维数组的数组名的二维数组:
	//    元素:| 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 
	//             p[0]      p[1]      p[2]      p[3]       p[4]     p[5]     p[6]
	//地址设为:| 0 1 2 3 | 4 5 6 7 | 8 9 a b | c d e f | 0 1 2 3 | 4 5 6 7 | 8
	//所以 &p[4][2] - &arr[4][2] == 12 - 16 == -4,再根据占位符的功能打印的结果为:FFFFFFFC(十六进制),-4(十进制)
	return 0;
}

考察:%p打印的是无符号十六进制的地址值
涉及:二维数组,占位符%p,数组指针。


(8)指针笔试题8

判断代码运行结果

#include<stdio.h>
int main() {
	char* arr[3] = { "hello", "world", "bite" };
	//arr[0] == &'h' , arr[1] == &'w', arr[2] == &'b'
	//即数组元素:&'h'| &'w' | &'b'
	//元素名:  arr[0]|arr[1]|arr[2]

	char** pa = arr;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

考查:字符指针在接收字符串时,接受的是字符串的首元素的地址
涉及:指针数组,占位符%s。


(9)指针笔试题9

判断代码运行结果

#include<stdio.h>
int main(){
	char* c[4] = { "hello", "world", "bite", "pengge" };
	//一级字符指针数组c:
	//       数组元素值:| &'h'| &'w'| &'b'| &'p'|
	//         元素类型:|char*|char*|char*|char*|
	//         元素意义:|指向"hello"的指针(一开始指向'h')|指向"world"的指针(一开始指向'w')|指向"bite"的指针(一开始指向'b')|指向"pengge"的指针(一开始指向'p')
	//           元素名:| c[0]| c[1]| c[2]| c[3]|
	//         地址设为:   0      1    2     3
	char** cp[4] = {c + 3, c + 2, c + 1, c};
	//二级字符指针数组cp:
	//         数组元素:|  3  |  2  |  1  |  0  |
	//           元素名:|cp[0]|cp[1]|cp[2]|cp[3]|
	//         地址设为:   a     b    c     d
	char*** cpp = cp;
	//    *cpp == &cp[0] == a
	printf("%s\n", **++cpp);
	//都只能先从cpp开始分析:
	//1.++cpp:cpp先自增1——*cpp = a + 1 == b;
	//2.**(++cpp):两次解引用——(1)*(++cpp) == b --> (2)**(++cpp) == 2;
	//3.%s的作用:从所给地址开始,一直打印字符至'\0'处,所以打印的结果为:bite
	printf("%s\n", *-- *++cpp + 3);
	//1.++cpp:cpp再自增1——*cpp = b + 1 == c;
	//2.*++cpp:解引用——*cpp == c;
	//3.-- *++cpp:c自减1——*c = 1 - 1 ==0;
	//4.*-- *++cpp:解引用——*c == 0;
	//5.*-- *++cpp + 3:一级字符指针 + 3——*0 = 'h' + 3 == 'l'(临时,不是真的加);
	//6.打印结果为:lo
	printf("%s\n", *cpp[-2] + 3);
	//1.cpp[-2]:cpp指向的值先减2再解引用——(1)cpp - 2——*cpp = c - 2 == a(临时,不是真的加);(2)*(cpp - 2)——*(cpp - 2) = a;
	//2.*cpp[-2]:再解引用——**(cpp - 2) == *a == 3;
	//3.*cpp[-2] + 3:一级字符指针 + 3——*3 = 'p' + 3 =='g'(临时,不是真的加);
	//4.打印结果为:gge
	printf("%s\n", cpp[-1][-1] + 1);
	//1.cpp[-1]:cpp指向的值先减1再解引用——(1)cpp - 1——*cpp = c - 1 == b(临时,不是真的加);(2)*(cpp - 2)——*(cpp - 2) = b;
	//2.cpp[-1][-1]:b指向的值先减1再解引用——(1)b - 1——*b = 2 - 1 == 1(临时,不是真的加);(2)*1——*1 = 'w';
	//3.cpp[-1][-1] + 1:一级字符指针 + 1——*1 = 'w' + 1 == 'o'(临时,不是真的加);
	//4.打印为:orld
	return 0;
}

考察:操作符的优先级只在操作数的相邻位置才考虑;++ 和-- 会真实改变变量存的数据
涉及:二级指针,操作符++和–,解引用。


快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

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

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

相关文章

【HarmonyOS】鸿蒙应用地理位置获取,地理名称获取

【HarmonyOS】鸿蒙应用地理位置获取&#xff0c;地理名称获取 一、前言 首先要理解地理专有名词&#xff0c;当我们从系统获取地理位置&#xff0c;一般会拿到地理坐标&#xff0c;是一串数字&#xff0c;并不是地理位置名称。例如 116.2305&#xff0c;33.568。 这些数字坐…

SimpleLive1.7.5 |适配手机和TV,聚合抖B虎鱼四大直播

SimpleLive是一款聚合多个直播平台的应用程序&#xff0c;内置虎牙、斗鱼、哔哩哔哩及抖音直播。提供无广告体验&#xff0c;支持弹幕显示调整、夜间模式切换等功能。用户无需登录即可关注不同平台的主播并查看其直播状态。 大小&#xff1a;14M 下载地址&#xff1a; 百度网…

泷羽sec:shell作业

⼀、⽤Shell写⼀个计算器 #!/bin/bash read -p "请输入表达式&#xff08;格式为 操作数1 运算符 操作数2&#xff0c;如 5 3&#xff09;&#xff1a;" expression a1$(echo $expression | awk {print $1}) a2$(echo $expression | awk {print $2}) a3$(echo …

ETL工具观察:ETLCloud与MDM是什么关系?

一、什么是ETLCloud ETLCloud数据中台是一款高时效的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。 工具特点 1.离线与实时集成&#xff1a;支持离线数据集成&#xff08;ETL、ELT&#xff09;和变更数据捕获&#xff08;CDC&#xff09;实…

轻NAS系统CasaOS设备安装小雅超集结合内网穿透实现自由访问海量资源

文章目录 前言1. 本地部署AList2. AList挂载网盘3. 部署小雅alist3.1 Token获取3.2 部署小雅3.3 挂载小雅alist到AList中 4. Cpolar内网穿透安装5. 创建公网地址6. 配置固定公网地址 前言 本文主要介绍如何在安装了轻NAS系统CasaOS的小主机中部署小雅AList&#xff0c;并使用A…

MATLAB 最小二乘点云拟合球 (89)

MATLAB 最小二乘点云拟合球 (89) 一、算法介绍二、算法实现1.代码2.结果这是缘,亦是最美的相见 一、算法介绍 球面拟合算法是一种通过数学方法将一组三维点(通常在三维空间中分布)拟合到一个理想的球形表面上。这个过程通常涉及使用最小二乘法来最小化实际数据点与拟合的…

【分页查询】.NET开源 ORM 框架 SqlSugar 系列

&#x1f4a5; .NET开源 ORM 框架 SqlSugar 系列 &#x1f389;&#x1f389;&#x1f389; 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列…

WebStorm快捷键保持跟Idea一致

修改连续行局部多选 在WebStorm中同时按下ctrl alt s&#xff1b; 选择KeyMap 输入Column Selection Mode选择快捷键, 右键选择Add Mouse Shortcut 按下alt 鼠标左键 如果出现占用的情况&#xff0c;直接删除其他使用该快捷键的地方即可&#xff1b; 修改跨行局部多选 在…

好书推荐《LangChain大模型AI应用开发实践》

Hi大家好&#xff0c;我是码银~ 今天我要给大家带来一本特别的书籍推荐——《LangChain大模型AI应用开发实践》。如果你对人工智能、自然语言处理或者正在寻找一种高效构建AI应用的方法&#xff0c;那么这本书绝对不容错过。 这本书是由哔哩哔哩知名UP主【老陈打码】&#xff0…

python使用openpyxl处理excel

文章目录 一、写在前面1、安装openpyxl2、认识excel窗口 二、基本使用1、打开excel2、获取sheet表格3、获取sheet表格 尺寸4、获取单元格数据5、获取区域单元格数据6、sheet.iter_rows()方法7、修改单元格的值8、向表格中插入行数据9、实战&#xff1a;合并多个excel 三、获取E…

Spire.PDF for .NET【页面设置】演示:旋放大 PDF 边距而不改变页面大小

PDF 页边距是正文内容和页面边缘之间的空白。与 Word 不同&#xff0c;PDF 文档中的页边距不易修改&#xff0c;因为 Adobe 不提供任何功能供用户自由操作页边距。但是&#xff0c;您可以更改页面缩放比例&#xff08;放大/压缩内容&#xff09;或裁剪页面以获得合适的页边距。…

SpringMVC:参数传递之日期类型参数传递

环境准备和参数传递请见&#xff1a;SpringMVC参数传递环境准备 日期类型比较特殊&#xff0c;因为对于日期的格式有N多中输入方式&#xff0c;比如: 2088-08-182088/08/1808/18/2088… 针对这么多日期格式&#xff0c;SpringMVC该如何接收&#xff0c;它能很好的处理日期类…

驱动篇的开端

准备 在做之后的动作前&#xff0c;因为win7及其以上的版本默认是不支持DbgPrint&#xff08;大家暂时理解为内核版的printf&#xff09;的打印&#xff0c;所以&#xff0c;为了方便我们的调试&#xff0c;我们先要修改一下注册表 创建一个reg文件然后运行 Windows Registr…

Spring 那些事【2】SpringCache 简介及应用?

一、简介 SpringCache 是Spring 提供的一整套的缓存解决方案&#xff0c;他不是具体的缓存实现&#xff0c;它只提供了一整套的接口和代码规范、配置、注解等&#xff0c;用于整合各种缓存方案。 Spring 从 3.1 开始定义了 org.springframework.cache.Cache 和 org.springfra…

C语言:指针与数组

一、. 数组名的理解 int arr[5] { 0,1,2,3,4 }; int* p &arr[0]; 在之前我们知道要取一个数组的首元素地址就可以使用&arr[0]&#xff0c;但其实数组名本身就是地址&#xff0c;而且是数组首元素的地址。在下图中我们就通过测试看出&#xff0c;结果确实如此。 可是…

2023年04-至今:宏图一号L2级系统几何校正影像(1、3、5m)

目录 简介 摘要 代码 网址推荐 机器学习 2023年04-至今&#xff1a;宏图一号L2级系统几何校正影像&#xff08;1、3、5m&#xff09; 简介 作为航天宏图“女娲星座”建设计划的首发卫星&#xff0c;航天宏图-1号可获取0.5米-5米的分辨率影像&#xff0c;具备高精度地形测…

挑战用React封装100个组件【009】

Hello&#xff0c;大家好&#xff0c;今天我挑战的组件是这样的&#xff01; 欢迎大家把项目拉下来使用哦&#xff01; 项目地址&#xff1a; https://github.com/hismeyy/react-component-100 今天还是用到了react-icons。这里就不过多介绍啦&#xff0c;大家可以在前面的挑战…

【每日刷题】Day162

【每日刷题】Day162 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 3302. 字典序最小的合法序列 - 力扣&#xff08;LeetCode&#xff09; 2. 44. 通配符匹配 - 力扣&…

什么工具可以解决团队协作障碍?

团队协作是现代工作环境中至关重要的一部分&#xff0c;但在实际操作中&#xff0c;很多团队面临着协作中的各种障碍。这些障碍不仅影响工作效率&#xff0c;也可能阻碍团队成员之间的合作与信任建设。根据Patrick Lencioni在《团队协作的五大障碍》中的理论&#xff0c;团队协…

基于Java Springboot线上约拍摄影预约微信小程序

一、作品包含 源码数据库全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui uniapp 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信开发者工…