【C语言】指针进阶(3)

news2024/11/24 10:37:50

目录

指针和数组笔试题解析

一维数组

字符数组

二维数组

指针笔试题


在前面两篇文章,我们已经学完了指针进阶的所有知识点。在这篇文章中,我们主要学习的是一些常见的笔试题的总结。

指针和数组笔试题解析

在做题之前,我们先复习一下之前关于数组名所学过的知识:

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

在32位平台上,地址的大小是4字节,在64位平台上,地址的大小是8字节。

一维数组

分析下面代码:

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));

 分析代码:

 数组名和&数组名的区别:

 

字符数组

分析下面代码:

char arr[] = { 'a','b','c','d','e','f' }
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));

代码分析:

 

分析下面代码:

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

分析:

strlen 是求字符串长度的库函数,它统计的是字符串中 '\0' 之前的字符个数, 如果没有 ‘\0’ 就会一直往后找。对于上面的数组arr,由于数组中不含 '\0', 所以用strlen求其长度的时候找不到 ‘\0’,便会返回一个随机值。这个随机值是数组越界访问后,strlen找到内存中某个\0返回的结果。

 对于下面这行代码:

 传的参数类型是数组的首元素,'a' 的ASCLL值是97,那就是将97作为地址传参,strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了。

 当我们运行时,程序会崩溃:

strlen可以传数组名和&数组名

对于这句代码:

我们给strlen传的参数是 &arr, 它的类型是 char(*)[6], 虽然不是char*的类型,但当传到strlen时,strlen的形参是const char* 类型的指针接收地址,所以&arr会被强制类型转化为char*.

所以传&arr和arr都是可以的。

strlen的参数类型:

 

分析下面代码:

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));

注意:当以双引号 “” 的形式初始化字符串是,字符串末尾会自动添加一个'\0'

代码分析:

 

 分析下面代码:

char arr[] = "abcdef";
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));

 代码分析: 

 

分析下面代码:

char* p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));

 代码分析:

 

p, &p, &p+1的关系:

 

分析下面代码:

char* p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));
printf("%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));

  代码分析:

 

二维数组

分析下面代码:

int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));

代码分析:

 

 对于二维数组:

关于sizeof的一点知识:

当sizeof()括号中带有表达式时,表达式的值并不会去计算,sizeof只会根据表达式的类型求出结果。比如下面的代码:

 打印的结果是:

 表达式 s=a+2 并没有计算。

 总结: 数组名的意义:

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。

2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名都表示首元素的地址。

 

指针笔试题

笔试题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;
}
//程序的结果是什么?

 解析:

 

 打印结果:

 

笔试题2:

 本题需要使用x86的环境

//由于还没学习结构体,这里告知结构体的大小是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;
}

要是p的值是0x100000,我们可以0x100000强制类型转化为 struct Test* 再赋给p:

 解析:

 打印结果:

 

笔试题3:

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

 对于ptr1指针进行分析:

  对于ptr2指针进行分析:

  打印结果:

 

笔试题4:

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

这道题有一个陷阱,稍不小心就会做错:

 这个数组在进行初始化的时候,是采取小扩括号的形式,并不是大括号。我们根据逗号表达式进行求值。

 打印结果:

 

笔试题5:

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

 分析:

 打印结果:

 

笔试题6:

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

 解析:

  打印结果:

笔试题7:

int main()
{
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
}

 解析:

 打印结果:

 

笔试题8:

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

首先,我们根据前三句代码,画出它们的指向关系:

 当执行第一句printf时:

  当执行第二句printf时:

 

  当执行第三句printf时:

  当执行第四句printf时:

 

好了,指针进阶系列的文章到这儿就结束了,感谢大家的支持哦

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

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

相关文章

第三讲:k8s核心概念和专业术语

序言&#xff1a;这里只对概念继续基础阐述&#xff0c;不做具体案例&#xff0c;这位博主写的特别详细&#xff0c;想要对k8s深入的了解可以跳转了&#xff0c;作为小白的我看的有点懵&#xff0c;毕竟没实践过 链接地址→ http://t.csdn.cn/ZYtEF 这篇文章写了将近两万字对各…

mybatis-plus 缓存深入实践(二)

mybatis-plus 缓存&#xff08;一&#xff09;回顾、缓存&#xff08;二&#xff09;深入实践

3D测量之圆柱轴线直线度测量

视频演示效果 圆柱轴线直线度测量 零、效果图 一、目标 测量圆柱轴线的直线度误差&#xff1b; 二、测量方法–轴截面法[1] 本文主要是通过最小二乘法确定各截面中心坐标值。由各截面测得的实际中心构成测得中心线。按误差评定方法进行数据处理&#xff0c;求出轴线的直线度误…

启动es容器错误

说明&#xff1a;启动es容器&#xff0c;刚启动就停止&#xff0c;查看日志&#xff0c;出现以下错误信息&#xff08;java.lang.IllegalArgumentException: Plugin [analysis-ik] was built for Elasticsearch version 8.8.2 but version 7.12.1 is running&#xff09; 解决&…

【状态估计】基于UKF、AUKF的电力系统负荷存在突变时的三相状态估计研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码及数据 &#x1f4a5;1 概述 基于UKF和AUKF的电力系统负荷存在突变时的三相状态估计研究是一种利用无迹卡尔曼滤波&#xff08;Unscented Kalman Filter, UKF&#xff09…

学习Dart语言---2023-07-23

环境搭建---windows Dart for WindowsDart installer for Windows. Installs the latest Dart SDK and Dartium.https://gekorm.com/dart-windows/选择标准版&#xff0c;下载安装&#xff0c;一直next 验证安装成功&#xff1a; IDEA中配置dart SDK 下载dart插件 创建dart文…

用Python脚本自动采集金融网站当天发布的免费报告

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 其间旦暮闻何物&#xff1f;杜鹃啼血猿哀鸣。 大家好&#xff0c;我是皮皮。 一、前言 前几天在Python群【林生】问了一个Python数据采集的问题&#x…

PCL点云处理之最小二乘直线拟合(2D| 方法2)(❤亲测可用❤)(二百零一)

PCL点云处理之最小二乘直线拟合(2D| 方法2)(❤亲测可用❤)(二百零一) 一、算法简介二、算法实现1.代码2.结果一、算法简介 在二百章中,我们介绍了一种最小二乘拟合直线点云(2D)的方法,可以获取直线方程系数k,b,这里介绍另一种拟合直线点云的方法,更为简单方便,结果…

引入第三方字体库 第三方字体库Google Fonts

googlefonts官方网站 googlefonts中国网站 本人是在微信小程序中引入 在static中建一个文件夹font-family 例如字体链接&#xff1a;https://fonts.font.im/css?familyKirangHaerang 将该链接的返回的资源的复制到css文件中 font-family.css /* [0] */ font-face {font-fam…

Linux学习之Ubuntu 20.04安装内核模块

参考博客&#xff1a;Ubuntu20.04编译内核教程 sudo lsb_release -a可以看到我当前的系统是Ubuntu 20.04.4&#xff0c;sudo uname -r可以看到我的系统内核版本是5.4.0-100-generic。 sudo apt-get install -y libncurses5-dev flex bison libssl-dev安装所需要的依赖。 su…

国密SSL优势及应用场景

国密SSL的优势主要有以下几点&#xff1a; 更高的安全性&#xff1a;国密算法采用的是国家密码管理局推荐的算法&#xff0c;相对于传统的SSL协议更加安全。 更好的性能&#xff1a;国密算法是国家密码管理局推荐的算法&#xff0c;其加密效率与密钥长度相比传统算法更高。 更…

Java集合之List

ArrayLsit集合 ArrayList集合的特点 ArrayList集合的一些方法 ①.add(Object element) 向列表的尾部添加指定的元素。 ②.size() 返回列表中的元素个数。 ③.get(int index) 返回列表中指定位置的元素&#xff0c;index从0开始。 public class Test {public static void m…

【Python学习笔记】记载解决Python报错HTTP Error 403: Forbidden的一波三折过程

【Python学习笔记】记载解决Python报错HTTP Error 403: Forbidden的一波三折过程 当前进度&#xff1a;还没有解决&#xff0c;但是已经尝试了好几种办法&#xff0c;此处做个记录&#xff0c;也许能帮上忙。 本帖是整理回顾帖&#xff0c;不是教程帖&#xff0c;追求一个完美…

QT日志调试系统(前台、后台、文件查看调试信息)

通过qInstallMessageHandler获取Qt的打印信息&#xff0c;将这些打印信息存放到一个Widget中&#xff0c;实现不通过后台就能查看日志信息。 实现方法如下&#xff1a; main.cpp #include "mainwidget.h" #include <QApplication> #include <QStyleFactory…

yum的安装和使用(包含安装过程中遇到的问题及解决方法)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

2022年十月份电赛OpenMV巡线方案详细代码分析(1)

前言 &#xff08;1&#xff09;马上要进行电赛了&#xff0c;机器识别是铁定会使用到的。为了防止出现去年十月份那种特殊的巡线方案。我在此分享出OpenMV巡线方案&#xff0c;并且进行讲解和分析如何更改。 &#xff08;2&#xff09;学习本文之前&#xff0c;需要学习&#…

通过nexus3部署公司内部的私有npm仓库

简介&#xff1a; 登录时使用默认用户admin&#xff0c;密码不知道就需要找默认的&#xff0c;点击Sign in时会提示你路径&#xff0c;这里我是这样查的&#xff0c;在linux服务器上输入以下命令 ​编辑 前言&#xff1a; 准备工作&#xff0c;可能需要一台linux服务器&#x…

Jenkins报警机制的配置与Linux的使用总结

先在钉钉中添加一个机器人 在Configure System中找到机器人选项&#xff0c;并且复制webhook到网络钩子&#xff0c;然后添加机器人的编号、名称和关键词&#xff0c;然后点击测试&#xff0c;如果显示测试成功则表示配置成功&#xff0c;最后保存 再到配置中勾选顶顶机器人的定…

19.matlab数据分析插值(matlab程序)

1.简述 数据插值的计算机制 数据插值是一种函数逼近的方法。 一维插值 Y1interp1(X,Y,X1,method) 二维插值 interp2():二维插值函数。 调用格式: Z1interp2(X,Y,Z,X1,Y1,method) 其中&#xff0c;X、Y是两个向量&#xff0c;表示两个参数的采样点, Z是采样点对应的函数值。X1…

flutter开发实战-Stagger Animation实现水波纹动画

flutter开发实战-实现水波纹动画&#xff0c;使用到了交织动画&#xff0c;实现三个圆逐渐放大与渐变的过程。 一、效果图 二、实现水波纹效果 实现水波纹动画&#xff0c;使用到了交织动画&#xff0c;实现三个圆逐渐放大与渐变的过程。 交织动画 有些时候我们可能会需要一些…