C语言——深入理解指针(5)

news2024/11/18 11:38:26

目录

1. sizeof和strlen的对比

1.1 sizeof

1.2 strlen

1.3 sizeof和strlen 的对比

2. 数据和指针题解析

2.1 一维数组

2.2 字符数组

2.2.1

2.2.2

2.2.3

2.2.4

2.2.5

2.2,6

2.3 二维数组

3. 指针运算题解析

3.1 例1

3.2 例2

3.3 例3

3.4 例4

3.5 例5

3.6 例6

3.7 例7


1. sizeof和strlen的对比

1.1 sizeof

sizeof是用来计算变量所占内存空间的大小,单位:字节

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

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

1.2 strlen

strlen 是用来求字符串长度的。

size_t strlen ( const char * str );

strlen 统计的是字符串开始到 \0 之前的字符串的字符个数。(strlen 找到 \0 就会停止,没有找到就会一直找下去)

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[3] = { 'a', 'b', 'c' };//没有\0
	char arr2[] = "abc";//a,b,c,\0
	printf("%d\n", strlen(arr1));//随机数
	printf("%d\n", strlen(arr2));
	return 0;
}

1.3 sizeof和strlen 的对比

sizeofstrlen

1. sizeof 是操作符

2. sizeof 计算操作数所占内存的大小,单位:字节

3. 不管内存中存什么数据

1. strlen 是库函数,使用时需要包含头文件<string.h>

2. strlen 是求字符串长度的,统计的是\0 之前字符的间隔个数

3. 关注内存中是否有 \0 如果没有 \0 ,就会持续往后找,可能会越界。

2. 数据和指针题解析

首先我们先来补充一个知识点

数组名:数组名一般表示数组首元素的地址,但是有2个例外,

1. sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节;

2. &数组名,数组名表示整个数组,取出的数组的地址;

除此之外,所有遇到的数组都是数组首元素的地址。

2.1 一维数组

int main()
{
	int a[] = { 1,2,3,4 };//a数组有4个元素,每个元素是int类型的数据
	printf("%d\n", sizeof(a));//计算的是整个数组的大小---16
	printf("%d\n", sizeof(a + 0));//计算的是首元素地址+0,也就是首元素地址,——4或8
	printf("%d\n", sizeof(*a));//计算的是首元素的大小--4
	printf("%d\n", sizeof(a + 1));//计算的是首元素地址+1,也就是第二个元素地址的大小,——4或8
	printf("%d\n", sizeof(a[1]));//计算的是下标为1的元素大小——4
	printf("%d\n", sizeof(&a));//&a—取出的是数组地址,但是数组地址也是地址,所以——4或8
	printf("%d\n", sizeof(*&a));//计算的是整个数组的大小——16
	printf("%d\n", sizeof(&a + 1));//&a—取出的是数组地址,&a+1是跳过整个数组后的地址,也是地址——4或8
	printf("%d\n", sizeof(&a[0]));//&a[0]是第一个元素的地址--4或8
	printf("%d\n", sizeof(&a[0] + 1)); //&a[0] + 1是第二个元素的地址——4或8
	return 0;
}

2.2 字符数组

2.2.1

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//计算的是整个数组元素的大小——6
	printf("%d\n", sizeof(arr + 0));//就是的是arr+0的地址,也就是数组第一个元素的地址——4或8
	printf("%d\n", sizeof(*arr));//计算的是数组的第一个元素的地址——1
	printf("%d\n", sizeof(arr[1]));//计算的是数组下标为1的元素——1
	printf("%d\n", sizeof(&arr));//&arr是整个数组的地址,但是数组地址也是地址——4或8
	printf("%d\n", sizeof(&arr + 1));//&arr—取出的是数组地址,&arr+1是跳过整个数组后的地址,也是地址——4或8
	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址——4或8
	return 0;
}

2.2.2

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));//访问错误,*arr是‘a’-97
	printf("%d\n", strlen(arr[1]));//访问错误,arr[1]是'b'
	printf("%d\n", strlen(&arr));//随机值
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//随机值
	return 0;
}

2.2.3

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//arr+0是数组的首元素地址,地址的大小——4/8
	printf("%d\n", sizeof(arr + 0));//
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));//&arr-是数组的地址,数组的地址也是地址,是地址大小就是4/8
	printf("%d\n", sizeof(&arr + 1));//&arr+1,跳过数组,指向的是数组后面的地址--4/8
	printf("%d\n", sizeof(&arr[0] + 1));
	return 0;
}

2.2.4

#include<string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//arr+0是数组首元素的地址:6
	printf("%d\n", strlen(*arr));//err   传递的是'a'
	printf("%d\n", strlen(arr[1]));//err	传递的是'b'
	printf("%d\n", strlen(&arr));//err		
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个的地址--5
	return 0;
}

2.2.5

int main()
{
	const char* p = "abcdef";
	printf("%d\n", sizeof(p));//计算的是指针变量的大小-4/8
	printf("%d\n", sizeof(p + 1));//p+1是’b‘的地址
	printf("%d\n", sizeof(*p));//'a'---1
	printf("%d\n", sizeof(p[0])); //p[0]=='a'---1字节
	printf("%d\n", sizeof(&p));//&p-是自己的地址--4/8
	printf("%d\n", sizeof(&p + 1));//4/8
	printf("%d\n", sizeof(&p[0] + 1));//(&p[0] + 1)是'b'的地址
	return 0;
}

2.2,6

int main()
{
	const char* p = "abcdef";
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	printf("%d\n", strlen(*p));//err
	printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5
	return 0;
}

2.3 二维数组

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//12*4=48个字节,数组名单独在sizeof内部
	printf("%d\n", sizeof(a[0][0]));//4
	printf("%d\n", sizeof(a[0]));//是第一行这个一维数组的数组名,数组名单独放置sizeof内部了--16
	printf("%d\n", sizeof(a[0] + 1));//a[0]是第一行这个一维数组的数组名,这里表示数组首元素
	//也就是a[0][0]的地址,a[0] + 1是a[0][1]的地址
	printf("%d\n", sizeof(*(a[0] + 1)));//a[0]][1]--4个字节
	printf("%d\n", sizeof(a + 1));//a是二维数组的数组名,但是没有&,也没有单独放在sizeof内部
	//所以这里的a是数组首元素的地址,应该是第一行的地址,a+1是第二行的地址----4/8
	printf("%d\n", sizeof(*(a + 1)));//第二行的数组名,计算的是第二行的大小--16
	printf("%d\n", sizeof(&a[0] + 1));///&a[0]是第一行的地址,&a[0]+1就是第二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//对第二行的地址解引用,计算的是第二行的大小--16
	printf("%d\n", sizeof(*a));//这里的a是第一行的地址,*a就是第一行---16
	//*a->*(a+0)--.a[0]
	printf("%d\n", sizeof(a[3]));//a[3]就是的是第四行的大小---16
	//因为sizeof内部的不都是不会真实计算
	return 0;
}

3. 指针运算题解析

3.1 例1

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);//0x100000+20=0x100014
	printf("%p\n", (unsigned long)p + 0x1);//0x100001
	printf("%p\n", (unsigned int*)p + 0x1);//ox100004
	return 0;
}

3.3 例3

#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]);
	return 0;
}

3.4 例4

//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
int main()
{
	int a[5][5];//int (*ptr)[5]=a
	int(*p)[4];//P是数组指针,指向的数组4个类型的元素
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//指针-指针点决斗者得到的是指针和指针之间的元素个数,FFFFFC,-4
	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));//a[1]//aa是首元素的地址,也就是第一行的地址,aa+1就是第二行的地址
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
	return 0;
}

3.6 例6

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

3.7 例7

#include <stdio.h>
int main()
{
	const char* c[] = { "ENTER","NEW","POINT","FIRST" };
	const char** cp[] = { c + 3,c + 2,c + 1,c };
	const char*** cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *-- * ++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST	cpp[2]-->*(cpp-2)
	printf("%s\n", cpp[-1][-1] + 1);//EW	cpp[-1][-1]-->*(*(cpp-1)-1)+1	
	return 0;
}

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

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

相关文章

DSShop移动商城网店系统 反序列化RCE漏洞复现

0x01 产品简介 DSShop是长沙德尚网络科技有限公司推出的一款单店铺移动商城网店系统,能够帮助企业和个人快速构建手机移动商城,并减少二次开发带来的成本。 以其丰富的营销功能,精细化的用户运营,解决电商引流、推广难题,帮助企业打造生态级B2C盈利模式商业平台。完备的电商…

EasyRecovery2024免费永久版手机数据恢复软件

EasyRecovery2024是一款操作安全、用户可自主操作的数据恢复方案&#xff0c;它支持从各种各样的存储介质恢复删除或者丢失的文件&#xff0c;其支持的媒体介质包括&#xff1a;硬盘驱动器、光驱、闪存、硬盘、光盘、U盘/移动硬盘、数码相机、手机以及其它多媒体移动设备。能恢…

将.tiff格式图片转换为可视化的png,jpg,bmp等格式(附代码)

目前常用的.tiff格式图片转png格式图片&#xff0c;搜了一下&#xff0c;多数都是第三方平台直接转换&#xff0c;需要米&#xff0c;其实大可不必&#xff0c;自己撸代码就可以直接转换。 TIFF&#xff08;Tagged Image File Format&#xff09;是一种灵活的位图格式&#xf…

探索人工智能领域——每日20个名词详解【day7】

目录 前言 正文 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如需转载&#xff0c;请事先与我联系以…

YITH Product Countdown Premium电商商城产品倒计时高级版插件

点击阅读YITH Product Countdown Premium电商商城产品倒计时高级版插件原文 YITH Product Countdown Premium电商商城产品倒计时高级版插件的作用通过显示优惠的剩余时间或特定产品的可用数量的倒计时来促进销售。 您如何从中受益&#xff1a; 您可以利用稀缺性原则来增加转…

Open Inventor 2023.2.1 Crack

Fixed Bugs List 2023.2 2023.2.1 Open Inventor 2023.2.1 MeshViz #OIV-4824 Crash in MeshViz PbNonLinearDataMapping::computeColor Cache #OIV-4867 SoText3 : Texture read access violation – CAS-44904 Core #OIV-4725 Invalid displayed PoCircle color…

虹科案例 | OPC UA SDK快速扩展VIMANA智能制造软件连接性

导读&#xff1a; 虹科Matrikon在为OPC兼容性构建软件方面享有盛誉&#xff0c;VIMANA也因此选择使用我们的FLEX OPC UA SDK来快速扩展其智能制造软件的连接性&#xff0c;从而使用户能够“收听”其所有兼容OPC UA的设备&#xff0c;本篇案例文章将带你了解OPC UA SDK的现实应用…

《python每天一小段》--(2)使用Paramiko库,批量操作linux服务器

使用Paramiko库&#xff0c;批量操作多Linux服务器 使用Paramiko库建立SSH连接并执行命令获取多个Linux服务器的磁盘信息。通过这个例子&#xff0c;你可以学习到如何使用Python自动化操作远程服务器。 操作如图&#xff1a; 查看了两台服务器的磁盘容量&#xff1a; 安装模…

【电路笔记】-电阻器额定功率

电阻器额定功率 文章目录 电阻器额定功率1、概述2、电阻功率&#xff08;P&#xff09;3、功率电阻器4、电阻器额定功率示例15、电阻器额定功率示例2 电能被电阻吸收&#xff0c;因为它是电压和电流的乘积&#xff0c;一些电阻将这种电能转化为热量。 1、概述 当电流由于电阻器…

正则表达式(3):入门

正则表达式&#xff08;3&#xff09;&#xff1a;入门 小结 本博文转载自 从这篇文章开始&#xff0c;我们将介绍怎样在Linux中使用”正则表达式”&#xff0c;如果你想要学习怎样在Linux中使用正则表达式&#xff0c;这些文章就是你所需要的。 在认识”正则表达式”之前&am…

【unity3D】unity中如何查找和获取游戏物体

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity中游戏物体的查找与获取 这里写自定义目录标题 获取当前物体的基本属性查找其它物体- 通过名称查找其它物体- 通过标签查找- 通过类…

微信开发者工具里面模拟操作返回、录屏、网络速度、截屏等操作

有时候可能因为自己开发的页面使用了自定义的样式&#xff0c;所以没有了左上角的导航返回&#xff0c;所以进入我自定义的页面后&#xff0c;想要返回的话&#xff0c;就可以用到这里面你的操作&#xff0c;或者想截屏了也可以直接使用里面的截屏&#xff0c;或者返回主页面等…

如何有效进行测试执行进度计划

测试执行通常都是处于软件测试生命周期的关键路径上&#xff0c;它不仅在测试过程中占有重要的地位&#xff0c;并且也会花费大量的测试时间。针对测试执行而进行的计划&#xff0c;即测试执行进度计划&#xff0c;是进行测试执行进度控制的基础。在进行测试执行进度计划制订的…

龙迅分配器LT86102UXE/LT86104UX,HDMI一分二/HDMI一分四

龙迅LT86102UXE描述; Lontium LT86102UXE HDMI2.0分配器具有1&#xff1a;2的分配器&#xff0c;符合HDMI2.0/1.4规范&#xff0c;最大6Gbps高速数据速率&#xff0c;自适应均衡RX输入和预先强调的TX输出&#xff0c;以支持长电缆应用程序&#xff0c;内部TX通道交换灵活的PCB…

C++进阶篇6---lambda表达式

目录 一、lambda表达式 1.引入 2、lambda表达式语法 二、包装器---function 1.引入 2.包装器介绍 三、bind 一、lambda表达式 1.引入 class Person { public:Person(int age,string name):_age(age),_name(name){} //private://方便后面的举例int _age;string _name…

全网最新最全的自动化测试教程:python+pytest接口自动化(9)-cookie绕过登录(保持登录状态

在编写接口自动化测试用例或其他脚本的过程中&#xff0c;经常会遇到需要绕过用户名/密码或验证码登录&#xff0c;去请求接口的情况&#xff0c;一是因为有时验证码会比较复杂&#xff0c;比如有些图形验证码&#xff0c;难以通过接口的方式去处理&#xff1b;再者&#xff0c…

【openssl】RSA 生成公钥私钥 |通过私钥获取公钥

通过博客&#xff1a;Window系统如何编译openssl 编译出openssl.exe&#xff08;位于apps文件夹下&#xff09;。 现在需要使用它获得公钥私钥、通过私钥获取公钥 目录 说明&#xff01;&#xff01;&#xff01; 一.定位openssl.exe目录 二、进入命令cmd 三、生成私钥 …

知虾数据工具:助力Shopee商家实现数据化运营的有力助手

在如今竞争激烈的电商市场中&#xff0c;了解市场趋势、优化产品和店铺运营、了解竞争对手等是商家取得成功的关键。而针对Shopee平台的知虾数据工具则为商家和市场分析师提供了一个强大的数据分析工具。本文将介绍知虾数据工具的主要功能&#xff0c;包括多站点数据分析、行业…

抖音视频水印怎么去除?这三个视频去水印技巧值得收藏!

抖音视频水印怎么去除&#xff1f;随着互联网的持续发展&#xff0c;越来越多的人选择使用视频分享平台来展示他们的生活与工作。然而&#xff0c;上传到这些平台上的许多视频常常遭到恶意水印的攻击&#xff0c;严重影响了观众的观看体验。今天&#xff0c;我们将分享三个视频…

一键式紧急报警柱系统

随着科技的不断发展&#xff0c;一键式紧急报警柱在我们的生活和工作中扮演着越来越重要的角色。在这篇文章中&#xff0c;我们将一起探究与一键式紧急报警柱有关的知识。 一键式紧急报警柱是一种常见的安全防护设备&#xff0c;能够在紧急情况下快速发出警报&#xff0c;保护…