指针的学习5

news2025/9/18 19:26:22

目录

sizeof和strlen的区别

sizeof

strlen

数组和指针笔试题解析

一维数组

字符数组

二维数组

指针运算笔试题解析

题目1:

题目2:

题目3:

题目4:

题目5:

题目6:

题目7:


sizeof和strlen的区别

sizeof

sizeof计算变量所占内存空间的大小,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小

sizeof只关注占用内存空间的大小,不在乎内存中存放什么数据

sizeof是单目操作符,不是函数!!!

#include <stdio.h>
int main()
{
	int a = 0;
	printf("%zd\n", sizeof(a));//4
	printf("%zd\n", sizeof(int));//4
	printf("%zd\n", sizeof a);//4——侧面证明了sizeof不是函数!函数调用要有括号
	return 0;
}

sizeof后面的()不进行计算!

	int b = 8;
	short s = 4;
	printf("%d\n", sizeof(s = b + 2));//2
	printf("%d\n", s);//4

C语言是编译型语言:test.c->编译->链接->test.exe->运行

strlen

strlen是C语言库函数(头文件是<string.h>),功能是字符串长度,函数原型如下:

size_t strlen(const char* str);

统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数(不算\0)

strlen函数会一直向后找\0字符,直到找到为止,所以可能存在越界查找

	size_t len = strlen("abc\0ef");
	printf("%zd\n", len);//3
	const char* str = "abcdef";
	printf("%zd\n", strlen(str));//6
	char arr[] = { 'a','b','c' };
	printf("%zd\n", strlen(arr));//随机值——找到\0

数组和指针笔试题解析

一维数组
#include <stdio.h>
int main()
{
	//数组名的理解:
	//数组名是数组首元素的地址,但是有两个例外:
	//sizeof(数组名)——数组名表示整个数组,计算的是整个数组的大小,单位是字节
	//&数组名——数组名表示整个数组,取出的是整个数组的地址
	int a[] = { 1,2,3,4 };//数组有4个元素
	printf("%zd\n", sizeof(a));//16=4*4
	printf("%zd\n", sizeof(a + 0));//4或8——a表示首元素地址,类型是int*, a+0还是首元素地址
	printf("%zd\n", sizeof(*a));//4——a是首元素的地址,*a就是首元素,大小是4个字节,*a==a[0]=*(a+0)
	printf("%zd\n", sizeof(a + 1));//4或8——a表示首元素地址,类型是int*,a+1就是第二个元素的地址
	printf("%zd\n", sizeof(a[1]));//4——第二个元素
	printf("%zd\n", sizeof(&a));//4或8——整个数组的地址,是地址就是4或8
	printf("%zd\n", sizeof(*&a));//16——数组a的大小,*和&相抵消
	//&a是数组的地址,类型是int(*)[4],对数组指针解引用访问的是数组

	printf("%zd\n", sizeof(&a + 1));//4或8——&a+1是跳过整个数组后的那个位置的地址,是地址就是4/8,是野指针
	printf("%zd\n", sizeof(&a[0]));//4或8
	printf("%zd\n", sizeof(&a[0] + 1));//4或8——数组第二个元素的地址
	return 0;
}
字符数组

代码1:

#include <stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6=6*1——计算数组大小
	printf("%d\n", sizeof(arr + 0));//4或8——数组首元素的地址,是地址就是4或8
	printf("%d\n", sizeof(*arr));//1——arr是首元素地址,*arr就是首元素,大小就是a的大小
	//*arr=arr[0]=*(arr+0)
	printf("%d\n", sizeof(arr[1]));//1——第二个元素的大小
	printf("%d\n", sizeof(&arr));//4或8——数组的地址
	printf("%d\n", sizeof(&arr + 1));//4或8——跳过整个数组得到的地址,指向数组后面的空间
	//&arr--char (*)[6]
	printf("%d\n", sizeof(&arr[0] + 1));//4或8——第二个元素的地址
	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));//arr+0是数组首元素地址,数组中没有\0,导致越界访问,结果是随机的
	//printf("%d\n", strlen(*arr));这个代码有问题
	//err——首元素a的地址,'a'的ASCII码值是97,相当于把97作为地址传递给了strlen,strlen得到的就是野指针
	//printf("%d\n", strlen(arr[1]));//err——b的ASCII码值是98,同上
	printf("%d\n", strlen(&arr));//数组的地址,起始位置是数组的第一个元素的位置,结束位置随机x
	printf("%d\n", strlen(&arr + 1));//跳过整个数组得到的地址,指向数组后面的空间,随机值x-6
	printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始向后统计,随机值x-1
	return 0;
}

代码3: 

#include <stdio.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7
	printf("%d\n", sizeof(arr + 0));//4或8——arr表示数组首元素地址,arr+0还是数组首元素地址,是地址就是4或8
	printf("%d\n", sizeof(*arr));//1——arr是首元素地址,*arr就是首元素,大小就是a的大小
	//*arr=arr[0]=*(arr+0)
	printf("%d\n", sizeof(arr[1]));//1——第二个元素的大小
	printf("%d\n", sizeof(&arr));//4或8——数组的地址
	printf("%d\n", sizeof(&arr + 1));//4或8——跳过整个数组得到的地址,指向数组后面的空间
	//&arr--char (*)[6]
	printf("%d\n", sizeof(&arr[0] + 1));//4或8——第二个元素的地址
	return 0;
}

代码4: 

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6——arr首元素的地址,arr+0还是首元素的地址,向后在\0之前有6个字符
	//printf("%d\n", strlen(*arr));
	//err——首元素a的地址,'a'的ASCII码值是97,相当于把97作为地址传递给了strlen,strlen得到的就是野指针
	//printf("%d\n", strlen(arr[1]));//err——b的ASCII码值是98,同上
	printf("%d\n", strlen(&arr));//6——数组的地址,起始位置是数组的第一个元素的位置
	printf("%d\n", strlen(&arr + 1));//跳过整个数组得到的地址,指向数组后面的空间,随机值
	printf("%d\n", strlen(&arr[0] + 1));//5
	return 0;
}

代码5: 

#include <stdio.h>
int main()
{
	const char* p = "abcdef";
	printf("%d\n", sizeof(p));//4或8——p是指针变量,指针变量的大小
	printf("%d\n", sizeof(p + 1));//4或8——p+1是b的地址,是地址就是4或8//
	printf("%d\n", sizeof(*p));//1——p的类型是const char*,*p就是char类型
	printf("%d\n", sizeof(p[0]));//1——第一个元素的大小
	printf("%d\n", sizeof(&p));//4或8——数组的地址
	printf("%d\n", sizeof(&p + 1));//4或8——跳过p指针变量后的地址,是地址就是4或8
	printf("%d\n", sizeof(&p[0] + 1));//4或8——第二个元素的地址
	return 0;
}

代码6:

#include <stdio.h>
#include <string.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	//printf("%d\n", strlen(*p));
	//err——首元素a的地址,'a'的ASCII码值是97,相当于把97作为地址传递给了strlen,strlen得到的就是野指针
	//printf("%d\n", strlen(p[0]));//err——b的ASCII码值是98,同上
	printf("%d\n", strlen(&p));//&p是指针变量p的地址,与字符串无关
	//从p这个指针变量的起始位置开始向后数,p变量存放的地址是什么,不知道,所以答案是随机值

	printf("%d\n", strlen(&p + 1));//跳过整个数组得到的地址,指向数组后面的空间,随机值(与上句无关,因为有可能存在\0)
	printf("%d\n", strlen(&p[0] + 1));//5
	return 0;
}
二维数组
#include <stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48——a是数组名,单独放在sizeof内部,计算的是整个数组的大小,单位是字节48=3*4*4
	printf("%d\n", sizeof(a[0][0]));//4——第一行第一个元素的大小
	printf("%d\n", sizeof(a[0]));//16——a[0]第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小16个字节
	printf("%d\n", sizeof(a[0] + 1));//4或8——a[0]第一行的数组名,但是a[0]并没有单独放在sizeof内部
	//a[0]就是数组首元素的地址,就是&a[0][0],a[0]+1即第一行第二个元素a[0][1],大小是4或8个字节
	printf("%d\n", sizeof(*(a[0] + 1)));//4——a[0][1]的大小
	printf("%d\n", sizeof(a + 1));//4或8——第二行地址的大小,a+1是数组指针,是地址大小就是4或8
	printf("%d\n", sizeof(*(a + 1)));//16——第二行的大小16=4*4
	printf("%d\n", sizeof(&a[0] + 1));//4或8——第一行第二个元素的地址,&a[0]就是数组第一行的地址,&a[0]+1就是第二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//16——第二行的大小
	printf("%d\n", sizeof(*a));//16——数组第一行的大小;*a==*(a+0)==a[0]
	printf("%d\n", sizeof(a[3]));//16——int [4],16=4*4;a[3]无需真实存在,仅仅通过类型的推断就能算出长度
	//a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小,16个字节
}

指针运算笔试题解析

题目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));//2,5
	return 0;
}
题目2:
#include <stdio.h>
//在X86环境下(32环境)
//假设结构体的大小是20个字节
//程序输出的结果是?
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;//结构体指针
//指针+-整数
int main()
{
    //0x1就是1
	printf("%p\n", p + 0x1);//00100014——结构体指针+1,要跳过整个结构体;0x100000+20->0x100014
	printf("%p\n", (unsigned long)p + 0x1);//00100001——不再是指针,long类型,整型值+1就是+1,0x100000+1->0x100001
	printf("%p\n", (unsigned int*)p + 0x1);//00100004——int*占4个字节
	return 0;
}
题目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]);//0
	return 0;
}
#include <stdio.h>
int main()
{
	int a[3][2] = { (0,1),(2,3),(4,5) };//逗号表达式,即{1, 3, 5},后面元素用0来填充
	int* p;
	p = a[0];
	printf("%d", p[0]);//1
	return 0;
}

题目4:
#include <stdio.h>
int main()
{
	int a[5][5];
	int(*p)[4];//p是一个数组指针,指向的数组是4个整型元素
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//FFFFFFFC,-4
	//a的类型:int (*)[5];p的类型是int (*)[4],一行四个元素
	//p[4][2]==*(*(p+4)+2)
	//两个指针之间相差4个元素
	//指针-指针的绝对值是指针和指针之间的元素个数
	return 0;
}
题目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*
	int* ptr2 = (int*)(*(aa + 1));//*(aa+1)==aa[1],aa[1]是第二行的数组名,数组名表示首元素的地址,aa[1]也是&aa[1][0]
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
	return 0;
}
题目6:
#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };//数组的每个元素都是char*,a是指针数组
	char** pa = a;
	pa++;
	printf("%s\n", *pa);//at
	return 0;
}
题目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);//POINT——cpp+1,指向c+2
	printf("%s\n", *-- * ++cpp + 3);
	//ER——复杂!+优先级最低,cpp+1+1解引用指向c+1,c+1-1即为c,解引用得到"ENTER"首字母,首字母+3得到ER
	printf("%s\n", *cpp[-2] + 3);//ST——*cpp[-2]+3即**(cpp-2)+3,cpp+2-2=cpp,指向c+3,指向FIRST,+3得到ST
	printf("%s\n", cpp[-1][-1] + 1);//EW——cpp[-1][-1]=*(*(cpp-1)-1);cpp+2-1=cpp+1,指向c+2,c+2-1=c+1指向NEW,+1得到EW
	return 0;
}

 

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

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

相关文章

Unity Shader实现UI流光效果

效果&#xff1a; shader Shader "UI/Unlit/Flowlight" {Properties{[PerRendererData] _MainTex("Sprite Texture", 2D) "white" {}_Color("Tint", Color) (1, 1, 1, 1)[MaterialToggle] PixelSnap("Pixel snap", float…

一个爬虫自动化数据采集的故事~

目录 一、原文二、故事前半段背景内容三、正经的讲点DrissionPage知识四、故事的收尾 一、原文 原文来自一个爬虫自动化数据采集的故事~ , 建议点击链接看文章末尾的视频笔者不擅长自动化&#xff0c;一个小小故事分享给大家&#xff0c;仅个人观点 二、故事前半段背景内容 …

【C++】c++入门之递归上 数值类

文章目录 前言一、 递归1.1 基本概念1.2 递归的过程1.3 使用场景 二、例题讲解问题一&#xff1a;1002 - 编程求解123...n问题二&#xff1a;1241 - 角谷猜想问题三&#xff1a;1108 - 正整数N转换成一个二进制数问题四&#xff1a;1088 - 求两个数M和N的最大公约数 三、练习问…

【扩散模型系列3】DiT开源项目

文章目录 DiT原始项目Fast-DiT readmeSamplingTraining训练之前的准备训练DiTPyTorch 训练结果改进训练效果 Evaluation (FID, Inception Score, etc.) 总结 DiT原始项目 该项目仅针对DiT训练&#xff0c;并未包含VAE 的训练 项目地址 论文主页 Fast-DiT readme 该项目仅针…

【毕业】 医药药店销售管理系统

1、引言 设计结课作业,课程设计无处下手&#xff0c;网页要求的总数量太多&#xff1f;没有合适的模板&#xff1f;数据库&#xff0c;java&#xff0c;python&#xff0c;vue&#xff0c;html作业复杂工程量过大&#xff1f;毕设毫无头绪等等一系列问题。你想要解决的问题&am…

OpenJDK 目前主要发展方向

Loom&#xff1a;得赶紧解决 synchronized pin 线程的问题&#xff08;据说 Java 23 会解决&#xff0c;现在有预览版&#xff09;。各个 Java 库需要改造原来使用 ThreadLocal 的方式&#xff1a;如果是为了穿参数&#xff0c;则可以使用 ScopedLocal&#xff1b;如果是对象池…

【leetcode热题】寻找旋转排序数组中的最小值 II

难度&#xff1a; 困难通过率&#xff1a; 38.7%题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如&#xff0c;数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。 请找出其中最小的…

激光打标机红光与激光不重合:原因及解决方案

激光打标机红光和激光不在一个位置的问题可能由多种原因导致。以下是一些可能的原因和解决方法&#xff1a; 1. 激光器光路调整不当&#xff1a;激光器光路调整不当会导致激光束偏移&#xff0c;从而使红光与激光不重合。解决方法是重新调整激光器的光路&#xff0c;确保激光束…

Session登陆实践

Session登陆实践 Session登录是一种常见的Web应用程序身份验证和状态管理机制。当用户成功登录到应用程序时&#xff0c;服务器会为其创建一个会话&#xff08;session&#xff09;&#xff0c;并在会话中存储有关用户的信息。这样&#xff0c;用户在与应用程序交互的整个会话…

C语言逗号运算符(,)

在C语言中&#xff0c;逗号运算符&#xff08;,&#xff09;用于在表达式中分隔多个子表达式&#xff0c;并按照从左到右的顺序依次计算这些子表达式。逗号运算符的运算结果是最后一个子表达式的值。 逗号运算符的底层行为是依次计算每个子表达式&#xff0c;并将每个子表达式…

SSM框架,MyBatis-Plus的学习(下)

条件构造器 使用MyBatis-Plus的条件构造器&#xff0c;可以构建灵活高效的查询条件&#xff0c;可以通过链式调用来组合多个条件。 条件构造器的继承结构 Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xf…

广度优先搜索和深度优先搜索

广度优先搜索 广度优先搜索&#xff08;Breadth-First-Search&#xff0c;BFS&#xff09;类似于二叉树的层序遍历算法&#xff08;借助队列&#xff09;&#xff0c;其基本思想是&#xff1a;首先访问起始顶点&#xff0c;接着由v出发&#xff0c;依次访问v的各个未访问过的邻…

git命令行提交——github

1. 克隆仓库至本地 git clone 右键paste&#xff08;github仓库地址&#xff09; cd 仓库路径&#xff08;进入到仓库内部准备提交文件等操作&#xff09; 2. 查看main分支 git branch&#xff08;列出本地仓库中的所有分支&#xff09; 3. 创建新分支&#xff08;可省…

纪年哥的文物挽救木牌

左&#xff08;江南制造局&#xff0c;曾国藩书天道酬勤&#xff0c;李鸿章少荃印&#xff0c;光绪三十四年制造&#xff09; 中&#xff08;汉阳兵工厂&#xff0c;民国二十六年制造&#xff0c;公元1937年七月七日&#xff0c;抗日战争全面爆发&#xff09; 右&#xff08;…

linux、windows 动态库与静态库的实现

动态库与静态库的实现 在使用keil的时候遇到这样一个事情&#xff0c;我调用了一个函数&#xff0c;只有函数声明&#xff0c;但是我想查看函数的实现却不行&#xff0c;为什么会这样&#xff0c;这不来了嘛, 我们在使用printf函数等&#xff0c;都是加上头文件直接调用&…

HarmonyOS NEXT应用开发案例——列表编辑实现

介绍 本示例介绍用过使用ListItem组件属性swipeAction实现列表左滑编辑效果的功能。 该场景多用于待办事项管理、文件管理、备忘录的记录管理等。 效果图预览 使用说明&#xff1a; 点击添加按钮&#xff0c;选择需要添加的待办事项。长按待办事项&#xff0c;点击删除后&am…

考研408 2014年第41题(二叉树带权路径长度【WPL】)

function.h(结构体)&#xff1a; // // Created by legion on 2024/3/5. //#ifndef INC_14_4_TREE_FUNCTION_H #define INC_14_4_TREE_FUNCTION_H #include <stdio.h> #include <stdlib.h>typedef int BiElemType; typedef struct BiTNode{BiElemType weight;//直…

【Python】Python Astar算法生成最短路径GPS轨迹

简介 最短路径问题是计算机科学中一个经典问题&#xff0c;它涉及找到图中两点之间距离最短的路徑。在实际应用中&#xff0c;最短路径算法用于解决广泛的问题&#xff0c;例如导航、物流和网络优化。 步骤 1&#xff1a;加载道路网络数据 要计算最短路径&#xff0c;我们需…

【Python】装饰器函数

专栏文章索引&#xff1a;Python 原文章&#xff1a;装饰器函数基础_装饰函数-CSDN博客 目录 1. 学习装饰器的基础 2.最简单的装饰器 3.闭包函数装饰器 4.装饰器将传入的函数中的值大写 5. 装饰器的好处 6. 多个装饰器的执行顺序 7. 装饰器传递参数 8. 结语 1. 学习装饰…

【UE5】创建蓝图

创建GamePlay需要的相关蓝图 项目资源文末百度网盘自取 在 内容游览器 文件夹中创建文件夹&#xff0c;命名为 Blueprints &#xff0c;用来放这个项目的所有蓝图(Blueprint) 在 Blueprints 文件夹下新建文件夹 GamePlay ,用存放GamePlay相关蓝图 在 Blueprints 文件夹下创建文…