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' };//没有\0char arr2[] = "abc";//a,b,c,\0printf("%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));//计算的是整个数组的大小---16printf("%d\n", sizeof(a + 0));//计算的是首元素地址+0,也就是首元素地址,——4或8printf("%d\n", sizeof(*a));//计算的是首元素的大小--4printf("%d\n", sizeof(a + 1));//计算的是首元素地址+1,也就是第二个元素地址的大小,——4或8printf("%d\n", sizeof(a[1]));//计算的是下标为1的元素大小——4printf("%d\n", sizeof(&a));//&a—取出的是数组地址,但是数组地址也是地址,所以——4或8printf("%d\n", sizeof(*&a));//计算的是整个数组的大小——16printf("%d\n", sizeof(&a + 1));//&a—取出的是数组地址,&a+1是跳过整个数组后的地址,也是地址——4或8printf("%d\n", sizeof(&a[0]));//&a[0]是第一个元素的地址--4或8printf("%d\n", sizeof(&a[0] + 1)); //&a[0] + 1是第二个元素的地址——4或8return 0;
}

2.2 字符数组

2.2.1

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

2.2.4

#include<string.h>
int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));//6printf("%d\n", strlen(arr + 0));//arr+0是数组首元素的地址:6printf("%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是第二个的地址--5return 0;
}

2.2.5

int main()
{const char* p = "abcdef";printf("%d\n", sizeof(p));//计算的是指针变量的大小-4/8printf("%d\n", sizeof(p + 1));//p+1是’b‘的地址printf("%d\n", sizeof(*p));//'a'---1printf("%d\n", sizeof(p[0])); //p[0]=='a'---1字节printf("%d\n", sizeof(&p));//&p-是自己的地址--4/8printf("%d\n", sizeof(&p + 1));//4/8printf("%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));//6printf("%d\n", strlen(p + 1));//5printf("%d\n", strlen(*p));//errprintf("%d\n", strlen(p[0]));//errprintf("%d\n", strlen(&p));//随机值printf("%d\n", strlen(&p + 1));//随机值printf("%d\n", strlen(&p[0] + 1));//5return 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]));//4printf("%d\n", sizeof(a[0]));//是第一行这个一维数组的数组名,数组名单独放置sizeof内部了--16printf("%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/8printf("%d\n", sizeof(*(a + 1)));//第二行的数组名,计算的是第二行的大小--16printf("%d\n", sizeof(&a[0] + 1));///&a[0]是第一行的地址,&a[0]+1就是第二行的地址printf("%d\n", sizeof(*(&a[0] + 1)));//对第二行的地址解引用,计算的是第二行的大小--16printf("%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=0x100014printf("%p\n", (unsigned long)p + 0x1);//0x100001printf("%p\n", (unsigned int*)p + 0x1);//ox100004return 0;
}

3.3 例3

#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };//里面的括号是小括号,所以表示的逗号表达式//所以真正的数组元素是1,3,5,其他都是0int* 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]=aint(*p)[4];//P是数组指针,指向的数组4个类型的元素p = a;printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//指针-指针点决斗者得到的是指针和指针之间的元素个数,FFFFFC,-4return 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,5return 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);//POINTprintf("%s\n", *-- * ++cpp + 3);//ERprintf("%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.mzph.cn/news/196341.shtml

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

相关文章

OpenCV介绍及安装

目录 1.OpenCV简介 2.OpenCV安装 3.检查OpenCV是否安装成功 4.OpenCV模块 5.学习技巧 1.OpenCV简介 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个基于开源发行的跨平台计算机视觉库&#xff0c;主要用于图像处理、计算机视觉和机器学习等领域…

干货|水表基础知识大全

第一部分 水表基础知识 第一节 水表的作用 水表:是用来记录流经自来水管道中水量的一种计量器具,也称为计量器具。 1、水表的发展简史 1825年英国的克路斯发明了真正具有仪表特征的平衡罐式水表以来&#xff0c;水表的发展已有近二百年的历史。期间&#xff0c;水表的结构…

目标检测中的损失函数:IOU_Loss、GIOU_Loss、DIOU_Loss和CIOU_Loss

文章目录 前言1.IOU_Loss&#xff08;Intersection over Union Loss&#xff09;2.GIOU_Loss&#xff08;Generalized Intersection over Union Loss&#xff09;3.DIOU_Loss&#xff08;Distance Intersection over Union Loss&#xff09;4.CIOU_Loss&#xff08;Complete In…

行云创新:与德国汽车业交流Catena-X数据空间技术有感

近日&#xff0c;行云创新CEO马洪喜先生受深圳高新投、Plug&Play邀请参加Catena-X技术研讨交流会&#xff0c;与西门子全球汽车生态系统总监Claus CREMERS&#xff0c;大众汽车全球数字化生产及流程负责人Frank GOELLER&#xff0c;宝马全球数字化政策负责人Sebastian SCHL…

【国际会议】2024年材料科学与机械应用发展国际会议(ICMSMAD 2024)

2024年材料科学与机械应用发展国际会议(ICMSMAD 2024) 2024 International Conference on Materials Science and Mechanical Application Development(ICMSMAD 2024) 一、【会议简介】 ​2024年材料科学与机械应用发展国际会议(ICMSMAD 2024)即将在美丽的中国成都盛大召开。这…

使用gdb调试正在运行的程序

写一个一秒打印一个数的c程序&#xff0c;并编译运行。 #include<unistd.h> #include<stdio.h> int main(int argc,char **argv){int i0;while(1){sleep(1);i;printf("%d\n",i);}return 0; }vim loop.c gcc loop.c -o loop ./loop 查看该进程的进程号。…

《数据库系统概论》学习笔记——王珊 萨师煊

第一章 绪论 一、数据库系统概述 1.数据库的4个基本概念 &#xff08;1&#xff09;数据 描述事物的符号记录称为数据 &#xff08;2&#xff09;数据库 存放数据的仓库 &#xff08;3&#xff09;数据库管理系统 主要功能&#xff1a; &#xff08;1&#xff09;数据定…

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…

SpringBoot:SpringMVC(上)

文章目录 前言一、SpringMVC是什么&#xff1f;1.1 MVC的定义&#xff1a;1.2 MVC 和 Spring MVC 的关系 二、Spring MVC 创建和连接2.1创建springmvc2.2接下来&#xff0c;创建⼀个 UserController 类&#xff0c;实现⽤户到 Spring 程序的互联互通&#xff0c;具体实现代码如…

MYSQL练题笔记-聚合函数-即时食物配送

我做完上一道题&#xff0c;决定总结一下了&#xff0c;因为现在还是没有一个我认为好的思路去构造语句&#xff0c;这里开始试一试新的思路。果然想要好一点的时候&#xff0c;总是像便秘一下&#xff0c;真的想拉&#xff0c;但是真的难拉啊 一、题目相关内容 1&#xff09…

科普关于msvcp140.dll文件是什么内容,解决msvcp140.dll丢失的修复方法

在使用电脑时出现了关于msvcp140.dll丢失的问题&#xff0c;这是什么情况&#xff0c;出现这样的问题通常都会导致电脑中的一些软件不能使用&#xff0c;那么都有什么办法能够解决msvcp140.dll丢失的问题呢&#xff1f;今天就给大家科普一些关于msvcp140.dll文件是什么的内容&a…

小程序长按识别二维码

小程序开发中要实现长按识别二维码的功能很简单&#xff0c;只需要在image标签里添加如下属性即可&#xff1a; 小程序版本&#xff1a; show-menu-by-longpress"{{true}}" uniapp版本&#xff1a; :show-menu-by-longpress"true" 举例&#xff1a; …

小红书种草笔记多少钱?给大家揭秘

小红书&#xff0c;一个以生活方式分享为主题的社交电商平台&#xff0c;吸引了众多年轻用户。种草笔记&#xff0c;是指用户在小红书上分享的关于某一产品或服务的使用体验、心得感悟&#xff0c;通过图文并茂的形式&#xff0c;激发其他用户的好奇心和购买欲望&#xff0c;从…

资深老鸟整理,高级测试工程师应具备的能力...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、业务熟悉 熟悉…

在国内Facebook广告怎么解决充值渠道问题?

怎么解决Facebook预充值跑广告营销的付款方式问题呢&#xff1f; Facebook跑广告是很多做出口营销的公司或团队喜欢的平台之一&#xff0c;那就避免不了需要支付给Facebook平台广告费用了&#xff0c;那到底用什么方式去充值到FB号上去解决呢&#xff1f;FB预充值有什么咔可以…

操作系统·设备管理

I/O系统是计算机系统的重要组成部分&#xff0c;是OS中最复杂且与硬件密切相关的部分 I/O系统的基本任务是完成用户提出的I/O请求&#xff0c;提高I/O速率以及改善I/O设备的利用率&#xff0c;方便高层进程对IO设备的使用 I/O系统包括用于实现信息输入、输出和存储功能的设备和…

stm32L071KB单片机字节对齐问题

字节对齐问题由来很关键 字节对齐问题由来 字节对齐问题由来 在移植同事代码的时候发现到一个赋值变量的地方就会出现死机&#xff0c;进入hardfault,怎么也找不不到原因&#xff0c;最后没办法去了github https://github.com/armink/CmBacktrace/blob/master/README_ZH.md Cm…

openGauss学习笔记-141 openGauss 数据库运维-例行维护-例行重建索引

文章目录 openGauss学习笔记-141 openGauss 数据库运维-例行维护-例行重建索引141.1 背景信息141.2 重建索引141.3 操作步骤 openGauss学习笔记-141 openGauss 数据库运维-例行维护-例行重建索引 141.1 背景信息 数据库经过多次删除操作后&#xff0c;索引页面上的索引键将被…

一次北斗接收机调试总结

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 最近项目中要用到北斗接收机&#xff0c;它的样子是长这样的&#xff1a; 这部机器里面是没有操作系统的&#xff0c;由单片机控制。最近我们要根据协议…

ChatGPT发布一年后,搜索引擎的日子还好吗?

导读&#xff1a;生成式AI&#xff0c;搜索引擎的终结者还是进化加速器 ChatGPT发布刚刚一年&#xff0c;互联网世界已经换了人间。 2023年&#xff0c;以ChatGPT和大模型为代表的生成式AI浪潮对全球互联网、云计算、人工智能领域都带来巨大冲击。而且生成式AI在各行各业的应用…