C语言之指针详解(5)(含有易错笔试题)

news2024/12/23 11:17:52

文章目录

  • 一、sizeof和strlen的对比
    • 1.1 sizeof
    • 1.2 strlen
    • 1.3 sizeof 和 strlen 的对比
  • 二、数组和指针笔试题
    • 2.1 一维数组
    • 2.2 字符数组
    • 2.3 二维数组
  • 三、指针运算笔试题
    • 3.1 题目1
    • 3.2 题目2
    • 3.3 题目3
    • 3.4 题目4
    • 3.5 题目5
    • 3.6 题目6
    • 3.7 题目7

一、sizeof和strlen的对比

有一个很神奇的现象,就是在C语言中sizeofstrlen是两个毫不相干的东西一个是操作符,一个是库函数。但是对于初学者来说就是很容易把两者弄混淆。下面我们就来进一步加深对这两个的学习。

1.1 sizeof

在学习操作符的时候,我们学习了 sizeofsizeof 计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。sizeof 只关注占用内存空间的大小,不在乎内存中存放什么数据。

比如:

#include <stdio.h>
int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof a);
	printf("%d\n", sizeof(int));

	return 0;
}

代码运行结果如下:
在这里插入图片描述

1.2 strlen

strlen是C语言库函数,功能是求字符串长度,函数原型如下:

size_t strlen(const char* str);

统计的是strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。strlen函数会一直向后找\0字符,直到找到为止,所以可能存在越界查找

示例代码如下:

#include <stdio.h>
int main()
{
	char arr1[3] = { 'a', 'b', 'c' };
	char arr2[] = "abc";
	printf("%d\n", strlen(arr1));
	printf("%d\n", strlen(arr2));

	printf("%d\n", sizeof(arr1));
	printf("%d\n", sizeof(arr2));
	return 0;
}

运行结果:
在这里插入图片描述

1.3 sizeof 和 strlen 的对比

sizeofstrlen
1. sizeof是操作符1.strlen是库函数,使用需要包含头文件string.h
2.sizeof计算操作数所占内存的大小,单位是字节2.strlen是求字符串长度的,统计的是\0之前字符的个数
3.不关注内存中存放什么数据3.关注内存中是否有\0,如果没有\0,就会持续往后找,可能会越界

对于下面的笔试题,有少部分我做了讲解。如果有其它疑问的地方可以在底下评论区问我,我会尽可能帮助大家。

二、数组和指针笔试题

在下面的题目中sizeof的情况比较简单,对于strlen有些地方稍微有点难度,我会为大家做出相应的解释。

2.1 一维数组

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

	return 0;
}

结果如下:
在这里插入图片描述

2.2 字符数组

代码1:

#include <stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	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));
	return 0;
}

结果如下:
在这里插入图片描述

代码2:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//没有\0因此会越界,导致随机值
	printf("%d\n", strlen(arr + 0));//没有\0因此会越界,导致随机值
	//printf("%d\n", strlen(*arr));arr代表首元素地址,*arr代表数组第一个元素'a','a'的ASCLL码值是97,
	//因此这里strlen函数会从地址为97的地方开始找\0来计算字符串长度,但地址为97的空间访问是非法的,是禁止的。
	//printf("%d\n", strlen(arr[1]));arr[1]代表'b'这个元素,道理同上面一个*arr的情况只不过这里是非法访问地址为98的。
	printf("%d\n", strlen(&arr));//地址和arr一样,只不过是数组的地址,但没有\0因此会越界,导致随机值
	printf("%d\n", strlen(&arr + 1));//由于+1跳过一整个数组,因此比上一个&arr的输出结果少了一个数组的长度6,但是还是没有\0因此会越界,导致随机值
	printf("%d\n", strlen(&arr[0] + 1));//是第二个元素'b'的地址,因此比第一个arr的输出结果少了1但是还是没有\0因此会越界,导致随机值。
	return 0;
}

输出结果如下:
在这里插入图片描述

代码3:

#include <stdio.h>
int main()
{
	char arr[] = "abcdef";
	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));
	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));arr代表首元素地址,*arr代表数组第一个元素'a','a'的ASCLL码值是97,
	//因此这里strlen函数会从地址为97的地方开始找\0来计算字符串长度,但地址为97的空间访问是非法的,是禁止的。
	//printf("%d\n", strlen(arr[1]));arr[1]代表'b'这个元素,道理同上面一个*arr的情况只不过这里是非法访问地址为98的。
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));//&arr是整个数组的地址,+1跳过整个数组,因此只能越界访问,结果就是随机值了
	printf("%d\n", strlen(&arr[0] + 1)); //是第二个元素'b'的地址,因此比第一个arr的输出结果少了1
	return 0;
}

运行结果如下:
在这里插入图片描述

代码5:

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

	return 0;
}

结果如下:
在这里插入图片描述

代码6:

经过上面的联系,我想大家都掌握的差不多了吧,最后一个留给大家自行思考,看看是否能解决。

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

2.3 二维数组

对于二维数组的情况需要注意的一个点就是,二维数组的数组名代表首元素地址时,这个首元素是指第一行元素的地址。

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

	return 0;
}

代码运行结果如下:
在这里插入图片描述

数组名的意义:

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

三、指针运算笔试题

3.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;
}
//程序的结果是什么?

3.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;
}

3.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;
}

3.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;
}

3.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;
}

3.6 题目6

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

3.7 题目7

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

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

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

相关文章

操作系统 - 输入/输出(I/O)管理

输入/输出(I/O)管理 考纲内容 I/O管理基础 设备&#xff1a;设备的基本概念&#xff0c;设备的分类&#xff0c;I/O接口 I/O控制方式&#xff1a;轮询方式&#xff0c;中断方式&#xff0c;DMA方式 I/O软件层次结构&#xff1a;中断处理程序&#xff0c;驱动程序&#xff0c;…

汇编:比较跳转

在16位汇编语言&#xff08;如x86汇编&#xff09;中&#xff0c;比较指令用于比较两个操作数的大小&#xff0c;通常用于条件跳转、循环控制等逻辑操作&#xff0c;比较指令&#xff08;如CMP&#xff09;会根据操作数的比较结果设置标志寄存器中的相关标志位 比较指令影响的…

KAN(Kolmogorov-Arnold Network)的理解 2

系列文章目录 第一部分 KAN的理解——数学背景 第二部分 KAN的理解——网络结构 文章目录 系列文章目录前言KAN网络结构&#xff1a;Kolmogorov-Arnold Network 前言 这里记录我对于KAN的探索过程&#xff0c;每次会尝试理解解释一部分问题。欢迎大家和我一起讨论。 KAN tuto…

Spring Boot集成六大常用中间件,附集成源码,亲测有效

目录 万字论文&#xff0c;从0到1&#xff0c;只需1小时获取途径1、Spring Boot如何集成Spring Data JPA&#xff1f;2、Spring Boot如何集成Spring Security&#xff1f;3、Spring Boot如何集成Redis&#xff1f;4、Spring Boot如何集成RabbitMQ&#xff1f;5、Spring Boot如何…

Dream

好像很多人梦寐以求的都是别人已经拥有的&#xff0c;多少人奋斗一生的目标&#xff0c;却只是别人的起点&#xff0c;人生而自由&#xff0c;只是不在枷锁之中&#xff0c;生活中没有人不遗憾&#xff0c;只是没有人喊疼&#xff0c;时间不会重来&#xff0c;已经过去了就让它…

day16--集合进阶(Set、Map集合)

day16——集合进阶&#xff08;Set、Map集合&#xff09; 一、Set系列集合 1.1 认识Set集合的特点 Set集合是属于Collection体系下的另一个分支&#xff0c;它的特点如下图所示 下面我们用代码简单演示一下&#xff0c;每一种Set集合的特点。 //Set<Integer> set ne…

软考 系统架构设计师系列知识点之SOME/IP与DDS(3)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之SOME/IP与DDS&#xff08;2&#xff09; 本文内容参考&#xff1a; 车载以太网 - SOME/IP简介_someip-CSDN博客 https://zhuanlan.zhihu.com/p/369422441 什么是SOME/IP?_someip-CSDN博客 SOME/IP 详解系列&#…

AS加密技术的实战应用与解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、AS加密技术简介 二、AS加密技术的实现过程 1. 生成公钥和私钥 2. 使用公钥加密数据 …

Java从坚持到精通-SpringBoot项目-多来米云客(持续更新中)

1.项目介绍 该项目模仿动力云客制作&#xff0c;是一款商业的集营销销售为一体的客户关系管理系统&#xff0c;其采用信息化、数字化方式来进行营销销售及客户管理。 云客指的是海量客户&#xff0c;通过技术方式实现的这一套系统&#xff0c;可用于自动化分析销售、市场营销…

【Python】 探索Python中的“命名元组”

基本原理 在Python中&#xff0c;元组&#xff08;tuple&#xff09;是一种不可变序列&#xff0c;它允许我们存储一系列的元素&#xff0c;并且这些元素一旦被创建就不能被修改。元组的这种不可变性使得它们在多线程编程中非常安全&#xff0c;因为不需要担心数据被意外修改。…

【VTKExamples::Utilities】第九期 FrameRate

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例FrameRate,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. FrameRate 该样例介绍 如…

详细分析 tar: xx:无法 open: 没有那个文件或目录 的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法 1. 问题所示 对于此问题处理起来比较简易&#xff0c;对此放置在运维的专栏模块 在执行解压的时候出现如下问题&#xff1a; (pgm37) l228l228:~/huoyanhao/pytorch-glow-master/pytorch-glow-master$ tar -xvf celeb-tfr.tar tar: …

“提升人工智能大模型智能:策略与挑战“

文章目录 每日一句正能量前言算法创新数据质量与多样性模型架构优化后记 每日一句正能量 失败时可以称为人生财富&#xff0c;成功时可以称为财富人生。 前言 随着人工智能技术的飞速发展&#xff0c;大模型已经成为推动多个领域创新的关键力量。从自然语言处理到图像识别&…

ssm145基于java的电脑硬件库存管理系统+jsp

电脑硬件库存管理系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对电脑硬件库存信息管理混乱&…

开源远程协助:分享屏幕,隔空协助!

&#x1f5a5;️ 星控远程协助系统 &#x1f5b1;️ 一个使用Java GUI技术实现的远程控制软件&#xff0c;你现在就可以远程查看和控制你的伙伴的桌面&#xff0c;接受星星的指引吧&#xff01; 支持系统&#xff1a;Windows / Mac / Linux &#x1f31f; 功能导览 &#x1f…

AI分析SP和pk进行sk分析

SP原始表行标题代表题目序号&#xff0c;列代表学生&#xff0c;如果学生答对题目为1&#xff0c;否则为0。问题知识点矩阵这个文件横轴代表每个知识点&#xff0c;列标题代表每个题目序号&#xff0c;如果题目包含这个知识点则该处值为1。通过两个文件判断学生对于每个知识点的…

行为设计模式之职责链模式

文章目录 概述原理代码实现小结 概述 职责链模式(chain of responsibility pattern) 定义: 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求.将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止. 在职责链模式中&…

文件上传漏洞:pikachu靶场中的文件上传漏洞通关

目录 1、文件上传漏洞介绍 2、pikachu-client check 3、pikachu-MIME type 4、pikachu-getimagesize 最近在学习文件上传漏洞&#xff0c;这里使用pikachu靶场来对文件上传漏洞进行一个复习练习 废话不多说&#xff0c;开整 1、文件上传漏洞介绍 pikachu靶场是这样介绍文…

【Leetcode 160】环形链表——双指针,细节讲解

题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

智能时代下,人机交互和虚拟现实的机遇和挑战

智能时代下,人机交互和虚拟现实的机遇和挑战