C语言:指针和数组(看完拿捏指针和数组)

目录

数组名的理解:

一维数组:

 解析:

 字符数组:

 解析: 

 解析:

字符串数组:

 解析: 

 解析: 

一级指针: 

 解析: 

 解析: 

二维数组:

 解析: 

指针笔试题:

题一:一维数组

题二: 结构体指针

题三: 一维数组

题四: 二维数组

题五: 二维数组

题六: 二维数组

题七:指针数组

题八: 指针数组(多级)

以上就是个人学习见解和学习的解析,欢迎各位大佬在评论区探讨!

感谢大佬们的一键三连! 感谢大佬们的一键三连! 感谢大佬们的一键三连!


数组名的理解:

数组名是数组首元素的地址;
但是有2个例外
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节;
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

代码中的4/8指的是在32位或者X86环境下位4个字节,在X64环境下是8个字节。 

一维数组:

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

 解析:

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

2、a不是单独放在sizeof()内部,也没有取地址,所以a就是首元素的地址,a+0还是首元素的地址,是地址大小就是4/8个字节。

3、*a中的a是数组首元素的地址,*a就是对首元素的地址解引用,找到的就是首元素,首元素的大小就是4个字节。

4、这里的a是数组首元素的地址,a+1是第二个元素的地址,sizeof(a+1)就是地址的大小

5、计算的是第二个元素的大小。

6、&a取出的数组的地址,数组的地址也就是个地址。

7、&a----> int( * )[ 4 ],   *&a----->int [ 4 ]。

8、&a取出的是数组的地址,&a--> int( * )[ 4 ],&a+1是从数组a的地址向后跳过一个(4个整型元素)数组的大小,&a+1还是地址,是地址就是4/8个字节。

9、&a[ 0 ]就是第一个元素的地址,计算的是地址的大小,是地址就是4/8个字节。

10、&a[ 0 ]+1就是第二个元素的地址,大小是4/8个字节,&a[ 0 ]+1---> &a[ 1 ] 。

 字符数组:

#include <stdio.h>int main()
{char arr[] = {'a','b','c','d','e','f'};printf("%d\n", sizeof(arr));//6printf("%d\n", sizeof(arr+0));//4/8printf("%d\n", sizeof(*arr));//1printf("%d\n", sizeof(arr[1]));//1printf("%d\n", sizeof(&arr));//4/8printf("%d\n", sizeof(&arr+1));//4/8printf("%d\n", sizeof(&arr[0]+1));//4/8return 0;
}

 解析: 

1、//数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,总共6个字节类型是char [6]。

2、//arr表示数组首元素的地址,arr+0还是数组首元素的地址,是地址就是4/8个字节,类型是char*。

3、//arr表示数组首元素的地址,*arr就是首元素,大小1个字节,类型是char。

4、//arr[1]就是第二个元素,大小是1个字节。

5、//&arr是数组的地址,但是数组的地址也是地址,是地址就是4/8。

6、//&arr + 1是跳过整个数组后的地址,是地址就是4/8个字节。

7、//第二个元素的地址,是4/8个字节。

#include <stdio.h>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));//错误printf("%d\n", strlen(arr[1]));//错误printf("%d\n", strlen(&arr));//随机值printf("%d\n", strlen(&arr+1));//随机值printf("%d\n", strlen(&arr[0]+1));//随机值return 0;
}

 解析:

1、因为字符数组arr中没有‘ \0 ’,所以在求字符串长度的时候,会一直往后找,产生的结构就是随机值。

2、arr + 0是首元素的地址,和第一个一样,也是随机值。

3、//错误, arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97;
//strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCII码值是97,那就是将97作为地址传参。
//strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了。

4、//错误

5、//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计。

6、//随机值

7、//&arr[0] + 1是第二个元素的地址。结果也是随机值。

字符串数组:

#include <stdio.h>int main()
{char arr[] = "abcdef";// a b c d e f \0printf("%d\n", sizeof(arr));//7printf("%d\n", sizeof(arr+0));//4printf("%d\n", sizeof(*arr));//1printf("%d\n", sizeof(arr[1]));//1printf("%d\n", sizeof(&arr));//4/8printf("%d\n", sizeof(&arr+1));//4/8printf("%d\n", sizeof(&arr[0]+1));//4/8return 0;
}

 解析: 

1、//7,类型是char [7]。

2、//arr + 0是首元素的地址。

3、//*arr其实就是首元素,1个字节,理解为*arr--> *(arr+0) -- arr[0]。

4、//arr[1]是第二个元素,1个字节。

5、//&arr是数组的地址,是地址就是4/8个字节。

6、//&arr + 1是跳过一个数组的地址,4/8。

7、//&arr[0] + 1是第二个元素的地址 4/8。

#include <stdio.h>int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));//6printf("%d\n", strlen(arr+0));//6printf("%d\n", strlen(*arr));//错误printf("%d\n", strlen(arr[1]));//错误printf("%d\n", strlen(&arr));//6printf("%d\n", strlen(&arr+1));//随机值printf("%d\n", strlen(&arr[0]+1));//5return 0;
}

 解析: 

由于与上面内容相同,就不做过多解释

1、//6

2、//6

3、//err

4、//err

5、//6

6、//随机值

7、//5

一级指针: 

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

 解析: 

1、//p是一个指针变量,大小就是4/8。

2、//p+1是'b'的地址,是地址大小就是4/8个字节。

3、//*p 就是'a'元素,就是1个字节。

4、//p[0]--> *(p+0) --> *p  1个字节。

5、//4/8,类型是&p -- char**。

6、//4/8

7、//4/8 , &p[0] + 1得到是'b'的地址 。

#include <stido.h>int main()
{char *p = "abcdef";printf("%d\n", strlen(p));//6printf("%d\n", strlen(p+1));//5printf("%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));//5return 0;
}

 解析: 

由于与上面内容相同,就不做过多解释

1、//6

2、//5

3、//err

4、//err

5、//随机值

6、//随机值

7、//5

二维数组:

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

 解析: 

1、//3*4*4 = 48

2、//4

3、//a[0]是第一行这个一维数组的数组名,数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节。

4、//a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&,a[0]表示数组首元素的地址,也就是a[0][0]的地址,所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节。

5、//4,计算的是就是第一行第2个元素的大小。

6、//4 / 8,a是数组首元素的地址,是第一行的地址 int(*)[4],a+1 就是第二行的地址。

7、//16,*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小,a+1 --> 是第二行的地址,int(*)[4],*(a+1) 访问的第二行的数组。

8、//4/8,&a[0]是第一行的地址 int(*)[4],&a[0]+1 是第二行的地址 int(*)[4]。

9、//16 计算的是第二行的大小。

10、//计算的是第一行的大小-16,a是数组首元素的地址,就是第一行的地址,*a 就是第一行,*a --> *(a+0) --> a[0]。

11、//16,类型是a[3]--> int [4]。

指针笔试题:

题一:一维数组

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

注意:&a+1的类型为int( * )[ 5 ],强制转换为int( * ).此时每次移动的就是4个字节,而不是20个字节了!

题二: 结构体指针

#include <stdio.h>
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

注意:整型就是正常的加减运算指针类型就需要加减n*类型的大小。 

题三: 一维数组

#include <stdio.h>int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf( "%x,%x", ptr1[-1], *ptr2);return 0;
}

注意: a强制转换成int类型+1就是正常加减,最后转换为指针int计算机会向后查找四个字节。

题四: 二维数组

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

注意: 注意二维数组中没有用{ }把数值包含,这里用的是( )是逗号表达式取最后一个值为元素a[ 0 ]可以看做&a[ 0 ][ 0 ].

题五: 二维数组

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

注意地址相减为相差的元素个数 ,此题为-4因为求的是地址,所以需要将-4转换成补码输出。

题六: 二维数组

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

注意:*(aa+1) = a[1] = &a[1][0]

题七:指针数组

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

注意:这里的a是指针数组,数组中每个位置的类型为char*。

题八: 指针数组(多级)

#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.rhkb.cn/news/106257.html

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

相关文章

SQL注入之HTTP头部注入

文章目录 cookie注入练习获取数据库名称获取版本号 base64注入练习获取数据库名称获取版本号 user-agent注入练习获取数据库名称获取版本号 cookie注入练习 向服务器传参三大基本方法:GPC GET方法&#xff0c;参数在URL中 POST&#xff0c;参数在body中 COOKIE&#xff0c;参数…

部署 ssm 项目到云服务器上(购买云服务器 + 操作远程云服务器 + 服务器中的环境搭建 + 部署项目到服务器)

部署 Web 项目 1、获取 Linux 环境1.1、如何去买一个云服务器1.2、远程操作云服务器1.3、在 Linux 系统中搭建 Java Web 的运行环境。1&#xff09;安装 JDK&#xff08;使用包管理器 yum 来安装&#xff09;2&#xff09; 安装Tomcat3&#xff09;安装 MySQL。 1.4、在云服务器…

【Python爬虫】使用代理ip进行网站爬取

前言 使用代理IP进行网站爬取可以有效地隐藏你的真实IP地址&#xff0c;让网站难以追踪你的访问行为。本文将介绍Python如何使用代理IP进行网站爬取的实现&#xff0c;包括代理IP的获取、代理IP的验证、以及如何把代理IP应用到爬虫代码中。 1. 使用代理IP的好处 在进行网站爬…

前端开发工具: VSCode

VSCode 安装使用教程&#xff08;图文版&#xff09; | arry老师的博客-艾编程 1. 下载 在官方网站&#xff1a;https://code.visualstudio.com/ 下载最新版本的 VSCode 即可 2. VSCode 常见插件安装 所有插件安装后,需要重启一下才生效 2.1 简体中文语言包 2.2 编辑器主…

贝叶斯公式中的动词 命名技巧

一项血液化验有95%的把我诊断某种疾病&#xff0c;但是&#xff0c;这项化验用于健康人也会有1%的“伪阳性”结果(即如果一个健康人接受这项化验&#xff0c;则化验结果乌镇此人患有该疾病的概率是0.01)。如果该疾病的患者事实上只占总人口的0.5%&#xff0c;若某人化验结果为阳…

CSS内边距和外边距属性

外边距属性用margin&#xff1b;padding属性叫填充&#xff0c;或者也叫内边距&#xff1b; margin:标签与标签的距离&#xff0c;到包围它的元素的边框的距离&#xff1b; padding&#xff1a;内边距&#xff0c;用于控制内容与边框之间的距离&#xff1b; CSS padding&…

框架分析(5)-Django

框架分析&#xff08;5&#xff09;-Django 专栏介绍Django核心概念以及组件讲解模型&#xff08;Model&#xff09;视图&#xff08;View&#xff09;模板&#xff08;Template&#xff09;路由&#xff08;URLconf&#xff09;表单&#xff08;Form&#xff09;后台管理&…

Unable to Locate package python2| Linux Ubuntu系统下python2的安装

Linux Ubuntu系统下python2的安装 FSL的安装脚本是用Python2写的&#xff0c;新版本的Ubuntu &#xff08;16以后&#xff09;在默认情况下没有安装Python2。在终端输入 python2&#xff0c;若提示没有相应的命令&#xff0c;则需要先安装Python2&#xff0c;如下指令&#xf…

【30天熟悉Go语言】10 Go异常处理机制

作者&#xff1a;秃秃爱健身&#xff0c;多平台博客专家&#xff0c;某大厂后端开发&#xff0c;个人IP起于源码分析文章 &#x1f60b;。 源码系列专栏&#xff1a;Spring MVC源码系列、Spring Boot源码系列、SpringCloud源码系列&#xff08;含&#xff1a;Ribbon、Feign&…

java八股文面试[数据结构]——List和Set的区别

List和Set是用来存放集合的接口&#xff0c;并且二者都继承自接接口Collection List 中的元素存放是有序的&#xff0c;可以存放重复的元素&#xff0c;检索效率较高&#xff0c;插入删除效率较低。 Set 没有存放顺序不能存放重复元素检索效率较低&#xff0c;插入删除效率较…

【自动电压调节器】无功功率控制的终端电压控制研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

[ VMware 虚拟机 ] 启动不了图形界面,报 “The system is running in low-graphics mode” 错误

文章目录 问题现象异常原因解决方案 问题现象 在启动虚拟机的时候&#xff0c;不能正常的进入图形界面&#xff0c;报 “The system is running in low-graphics mode” 错误。 异常原因 启动界面的xorg.conf文件失败并删除。 解决方案 1、点击异常界面上的 “ok”后&…

loss.sum.backward()为什么要sum()?

在动手学深度学习中&#xff0c;这样解释的&#xff1a; 当y不是标量时&#xff0c;向量y关于向量x的导数的最自然解释是一个矩阵。 对于高阶和高维的y和x&#xff0c;求导的结果可以是一个高阶张量。 然而&#xff0c;虽然这些更奇特的对象确实出现在高级机器学习中&#xff…

JetBrains 2023.2全新发布!IDEA、PyCharm等支持AI辅助

日前JetBrains官方正式宣布旗下IDE系列今年第二个重要版本——v2023.2全新发布&#xff0c;涵盖了 IntelliJ IDEA、PyCharm、WebStorm等一众知名产品&#xff0c;接下来我们一起详细了解一下他们的更新重点吧~ IntelliJ IDEA v2023.2——引入AI辅助开发 IntelliJ IDEA 2023.2…

vue关闭弹窗刷新父页面 this.$refs

代码截图 主页面 弹出框页面 接这一篇文章后续 参考链接

【javaweb】学习日记Day3 - Ajax 前后端分离开发 入门

目录 一、Ajax 1、简介 2、Axios &#xff08;没懂 暂留&#xff09; &#xff08;1&#xff09;请求方式别名 &#xff08;2&#xff09;发送get请求 &#xff08;3&#xff09;发送post请求 &#xff08;4&#xff09;案例 二、前端工程化 1、Vue项目-目录结构 2、…

拒绝摆烂!C语言练习打卡第六天

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;每日一练 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、选择题 &#x1f4dd;1.第一题 &#x1f4dd;2.第二题 &#x1f4d…

pgadmin4中的备份与恢复

一&#xff0c;postgresql 数据的备份与恢复 &#xff08;一&#xff09;数据库备份与恢复 1&#xff0c;备份 windows环境 1> dump 逻辑备份 1&#xff0c;用管理员身份打开power shell 2&#xff0c;切换到本机 postgresql 安装目录下的 bin 目录&#xff1a; PS C…

win开机自启jar包

下载winsw工具 只需下载图中红框的工具 https://github.com/winsw/winsw/releases 文件配置 将下载的文件与jar文件放置在一起&#xff0c;两个文件名修改为服务名 编辑xml文件 注意不要出现中文&#xff0c; 标签内的jar文件地址要改为自己目录 <service><!-- I…

MySQL每日一练--校园教务系统

一丶数据库名称&#xff1a;SchoolDB 二丶数据库表信息&#xff1a;角色信息表 表名&#xff1a; t_role 主键&#xff1a; r_id 序号 字段名称 字段说明 类别 位数 属性 备注 1 r_id 角色编号 int 主键 自动增长 2 r_name_EN 角色名&#xff08;英…