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

目录

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

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

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

相关文章

python中的进制转换和原码,反码,补码

python中的进制转换和原码,反码,补码 计算机文件大小单位 b bit 位(比特) B Byte 字节 1Byte 8 bit #一个字节等于8位 可以简写成 1B 8b 1KB 1024B 1MB 1024KB 1GB 1024MB 1TB 1024GB 1PB 1024TB 1EB 1024PB 进制分类 二进制:由2个数字组成,有0 和 1 pyth…

如何无线桥接路由器,让你的网络覆盖范围变大,做到网络信号无缝连接

你是否希望通过在两个路由器之间创建无线网桥(网络桥接)来扩大网络覆盖范围?好吧,你来对地方了!在当今日益互联的世界,拥有一个强大可靠的网络比以往任何时候都更重要。 无线网桥允许你无线连接两个或多个路由器,有效地扩展网络覆盖范围,并在更大的区域提供无缝的互联…

巧借C++算法实现冒泡排序算法

目录 引言冒泡排序原理具体实现步骤示例代码时间复杂度和稳定性优化可能性结束语 引言 作为计算机专业出身的开发者&#xff0c;以及从事软件开发相关的小伙伴&#xff0c;想必对C语言并不陌生&#xff0c;它是一门非常厉害的编程语言&#xff0c;不仅是基于程序底层的语言&a…

Proteus8.16仿真软件安装图文教程(Proteus 8 Professional)

Proteus8.16 &#x1f527;软件安装包下载链接&#xff1a;&#x1f527;视频教程&#x1f527;1 安装软件解压&#x1f527;2 安装&#x1f527;3 破解&#x1f527;4 汉化 &#x1f527;软件安装包下载链接&#xff1a; Proteus8.16软件下载链接 1、本文关于Proteus8.16 SP…

关于“你对SpringCloud的理解”

看看普通人和高手是如何回答这个问题的&#xff1f; 普通人 Spring Cloud 是一套微服务解决方案 它包括配置中心、RPC 通信、服务注册、服务熔断等组件 高手 Spring Cloud 是一套 分布式微服务的技术解决方案 它提供了快速构建分布式系统的 常用的一些组件 比如说配置…

人工智能与供应链行业融合:开启智能化供应链的新时代

随着人工智能技术的快速发展&#xff0c;供应链行业正迎来革命性变革。本文将探索人工智能在供应链管理中的应用领域&#xff0c;并分析其带来的益处和挑战&#xff0c;展望人工智能与供应链融合的未来发展趋势。 引言 供应链管理是企业运营中不可或缺的重要组成部分。它涵盖了…

Typora免费版安装教程(仅供学习)

目录 一、Typora简介二、Typora安装三、Typora补丁四、Typora使用体验五、总结 一、Typora简介 Typora是一款非常流行的Markdown编辑器&#xff0c;它能够将Markdown文本转化为漂亮的排版&#xff0c;并且支持实时预览。Typora具有简单易用的界面&#xff0c;使得用户可以轻松地…

微机原理9

一、单项选择题(本大题共15小题,每小题3分、共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 8088 系统的内存最大容量为 16MB. 其地址总线为&#xff08;&#xff09; A. 16 位 B. 20 位 C. 24 位 D. 32 位 2,以CPU为核心…

鸿宇多用户商城user.php RCE漏洞复现

0x01 产品简介 鸿宇多用户商城是一款支持各行业的多商家入驻型电商平台系统,商家版APP,微信商城,小程序及各种主流营销模块应有尽有,是一个功能强大的电子商务平台,旨在为企业和个人提供全面的在线购物解决方案。 0x02 漏洞概述 鸿宇多用户商城 user.php 存在任意命令执行漏洞…

无人机停机坪的主要功能有哪些

随着无人机行业领域的不断完善&#xff0c;无人机停机坪作为一项关键基础设施&#xff0c;正发挥着越来越重要的作用。无人机停机坪也叫无人机机巢、无人机机库、无人机机场。无人机停机坪不仅是无人机的“家”&#xff0c;更是其高效运行的关键环节。让我们一同探索无人机停机…

SQL Sever 基础知识 - 数据筛选(3)

SQL Sever 基础知识 - 四、数据筛选 第7节 BETWEEN7.1 BETWEEN 运算符概述7.2 BETWEEN 示例7.2.1 BETWEEN 与数字示例7.2.2 BETWEEN 和日期示例 第8节 LIKE8.1 LIKE运算符概述8.2 转义字符8.3 LIKE 示例8.3.1 % (百分号) 通配符示例8.3.2 _(下划线)通配符示例8.3.3 [字符列表] …

【Qt开发流程】之定时器事件与随机数示例

描述 QObject是所有Qt对象的基类&#xff0c;提供了Qt中基础的定时器支持。通过QObject::startTimer()函数&#xff0c;可以使用毫秒为单位的时间间隔来启动一个定时器。该函数返回一个唯一的整数定时器ID。该计时器现在将以规律的间隔触发&#xff0c;直到显式调用QObject::k…

安卓apk抓包(apk抓不到包怎么办)

起因 手机&#xff08;模拟器&#xff09;有时候抓不到apk的包&#xff0c;需要借助Postern设置一个代理&#xff0c;把模拟器的流量代理到物理机的burp上。 解决方案 使用Postern代理&#xff0c;把apk的流量代理到burp。 Postern是一个用于代理和网络流量路由的工具&#xf…

智能优化算法应用:基于黑猩猩算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于黑猩猩算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于黑猩猩算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黑猩猩算法4.实验参数设定5.算法结果6.参考文献7.…

根文件系统lib库添加与初步测试

一. 简介 我们在编译 busybox源码时&#xff0c;选择的是动态编译&#xff0c;所以&#xff0c;制作生成的 根文件系统中/bin或 /sbin目录下软件运行时会调用到一些库文件的。库文件就是交叉编译器的库文件。 前面我们编译 busybox源码时&#xff0c;选择动态编译&#xff0…

APP逆向工具环境安装

环境安装及配置&#xff1a; 1.JDK安装及配置链接&#xff1a;https://pan.baidu.com/s/146I4vDJdz8YeR0OEqLS8xw 提取码&#xff1a;7h00 2.SDK环境配置链接&#xff1a;https://pan.baidu.com/s/1A8rwqyw8Nn7p93Axqpll3A 提取码&#xff1a;cwv43.NDK环境配置链接&#xff1…

YITH WooCommerce Social Login跨境电商网站社交登录高级版插件

点击阅读YITH WooCommerce Social Login跨境电商网站社交登录高级版插件原文 YITH WooCommerce Social Login跨境电商网站社交登录高级版插件让您的用户节省时间并通过他们的社交资料之一登录或注册网站。 您如何从中受益&#xff1a; 用户无需填写表格、插入个人数据&#…

华清远见嵌入式学习——C++——作业5

作业要求&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;//沙发 类 class Sofa { private:string sitting; //是否可坐double *cost; //花费 public://无参构造函数Sofa(){}//有参构造函数Sofa(string s,double c):sitting(s),cost(new double(…

Python面向对象练习

Python面向对象练习 class Enty:blood100name""atackvalue100team0domain[1] #1,land 2 airdef setTeam(self,team0):self.teamteamdef atack(self,Enty):if self.teamEnty.team:print("不能向盟军开火")self.info()passelse :# print(self.domain)ss…

Python入门07循环及常见的数据结构

目录 1 循环的语法结构2 break和continue的示例3 可迭代对象4 列表5 元组6 列表和元组的应用场景7 集合8 字典9 生成器 1 循环的语法结构 在Python中&#xff0c;循环是一种控制结构&#xff0c;用于重复执行一段代码&#xff0c;直到满足特定条件。Python中有两种循环结构&am…