指针的深入理解(七)

指针的深入理解(七)

个人主页:大白的编程日记
个人专栏:C语言学习之路
感谢遇见,我们一起学习进步!


文章目录

  • 指针的深入理解(七)
    • 前言
    • 一.常量字符串指针
      • 1.1常量字符串的理解
      • 1.2常量字符串指针
    • 二.字符指针练习
      • 2.1sizeof
      • 2.2验证
      • 2.3strlen
      • 2.4验证
    • 三. 指针运算笔试题解析
      • 3.1笔试题一
      • 3.2笔试题二
      • 3.3笔试题三
      • 3.4笔试题四
      • 3.5笔试题五
      • 3.6笔试题六
      • 3.7笔试题七
      • 3.8验证
    • 后言

前言

哈喽,大家好!今天继续带大家学习没讲完的指针练习讲解。话不多说,直接进入正题。向着大厂冲锋!杀gigi!在这里插入图片描述


一.常量字符串指针

1.1常量字符串的理解

char* p = "abcdef";//常量字符串,末尾自动补\0

什么是常量字符串?像这种放在双引号内部的字符串就是常量字符串。
那常量字符串有什么不同之处吗?

首先:
常量字符串不可修改。
其次:
常量字符串末尾自动补\0。
这是两个非常重要的知识点,只要掌握好这两个知识点。我们接下来解题就会事半功倍。

  1. 结论一:常量字符串不可修改。
  2. 结论二:常量字符串末尾自动补\0。

1.2常量字符串指针

顾名思义,常量字符串指针就是指向常量字符串的指针。

char* p = "abcdef";//常量字符串,末尾自动补\0

那按理说常量字符指针应该是指向整个字符串的地址。
是不是呢?

其实并非如此。常量字符串指针指向的不是整个字符串的地址,
而是字符串首字符的地址,我们打印时,只需要知道字符串首字符的地址,就能打印整个字符串。

  1. 结论三:常量字符串指针指向的不是整个字符串的地址,
    指向的是首字符的地址。

二.字符指针练习

2.1sizeof

我们知道前面的常量字符串知识点后,来做题巩固一下吧。
看看我们对常量字符串的理解是否深入。

	char* p = "abcdef";//常量字符串,末尾自动补\0printf("%d\n", sizeof(p));//1printf("%d\n", sizeof(p + 1));//2printf("%d\n", sizeof(*p));//3printf("%d\n", sizeof(p[0]));//4printf("%d\n", sizeof(&p));//5printf("%d\n", sizeof(&p + 1));//6printf("%d\n", sizeof(&p[0] + 1));//7
	printf("%d\n", sizeof(p));//1//p是常量字符串指针,指向字符a.//是指针大小就是4/8字节
printf("%d\n", sizeof(p + 1));//2//p指向首字符,p+1跳过一个字符,指向字符b//还是指针,大小就是4/8字节
printf("%d\n", sizeof(*p));//3//p指向首字符,*p就是字符a//大小就是字符大小,就是1字节
	printf("%d\n", sizeof(p[0]));//4//思路一:p[0]--*(p+0)--*p--字符a,大小就是1字节//思路二:把字符串想象成数组,p是数组名,//p[0]就是首元素,大小就是1字节
printf("%d\n", sizeof(&p));//5//指针p也有自己的地址和空间,&p取出的是p指针的地址,//地址就是指针,大小就是4/8字节

printf("%d\n", sizeof(&p + 1));//6//指针p也有自己的地址和空间,&p取出的是p指针的地址,//&p指向的是p变量,&p+1就是跳过p指针后的地址//地址就是指针,是指针大小就是4/8字节
printf("%d\n", sizeof(&p[0] + 1));//7//p[0]就是字符a,&p[0]就是字符a的地址,//&p[0]+1跳过一个字符,指向字符b的地址//还是指针,大小就是4/8

2.2验证

  • 64位环境:
  • 32位环境:

2.3strlen

char* p = "abcdef";//常量字符串,末尾自动补\0
printf("%d\n", strlen(p));//1
printf("%d\n", strlen(p+1));//2
printf("%d\n", strlen(*p));//3
printf("%d\n", strlen(p[0]));//4
printf("%d\n", strlen(&p));//5
printf("%d\n", strlen(&p+1));//6
printf("%d\n", strlen(&p[0]+1));//7
printf("%d\n", strlen(p));//1
//p是常量字符数组首字符的地址,从a开始统计,6个字符
printf("%d\n", strlen(p+1));//2
//p是常量字符数组首字符的地址,p+1跳过一个字符
//指向b,从b开始统计,5个字符
printf("%d\n", strlen(*p));//3
//p是首字符,*p==字符a,字符a的ascll码值是97
//相当于把97作为地址传给strlen
//strlen接收的是野指针,代码有问题
printf("%d\n", strlen(p[0]));//4
//p[0]也是首字符,也相当于把97作为地址传给strlen
//strlen接收的也是野指针,代码也是有问题的

printf("%d\n", strlen(&p));//5
//p是指向首字符的指针,也有自己独立的空间的地址
//&p取出的是p的地址,和字符串关系不大
//什么时候遇到\0也不知道,是随机值

printf("%d\n", strlen(&p+1));//6
//p是指向首字符的指针,也有自己独立的空间的地址
//&p取出的是p的地址,&p+1跳过就是跳过p后的地址
//什么时候遇到\0也不知道,是随机值


那这两个随机值有没有什么关系呢?

如果\0的位置在p的后面的话,他们会相差4\8。
但是如果\0在p的内部的话,那他们就没有关系。
所以这两个随机值的没有啥太大的关系。
7.

printf("%d\n", strlen(&p[0]+1));//7
//p[0]是首字符,&p[0]取出的是首字符的地址
//&p[0]+1跳过一个字符,指向字符b
//从字符b统计,5个字符

2.4验证

  • 64位环境:
  • 32位环境:

三. 指针运算笔试题解析

接下来我们再来看几道指针运算题(有一道是阿里巴巴的!)

3.1笔试题一

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

我们先看ptr指针。

 int *ptr = (int *)(&a + 1); 


接下来再来看看*(a+1).

 printf( "%d,%d", *(a + 1), *(ptr - 1));


所以答案应该是2和5.
这里我们来验证一下对不对。


  • 验证:


3.2笔试题二

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>//在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);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}
//程序的结果是什么?

这道题涉及到我们指针一个非常重要的知识点。
那就是指针加减整除,移动多大距离取决于,指针的类型。

我们一个一个来看

*p = (struct Test*)0x100000;
printf("%p\n", p + 0x1);

p是结构体指针,题目又说,结构体的大小是20,所以p+1指针向前移动20个字节,但是p的地址是十六进制表示,1*16=4=20。
所以第一个结果应该是0x100014.

printf("%p\n", (unsigned long)p + 0x1);

p被强制类型转化为unsigned long,所以此时p不是指针了,
而是整型,整型+1就是+1。所以结果是0x100001。

	printf("%p\n", (unsigned int*)p + 0x1);

p被强制类型转化为unsigned int*,此时p是整形指针,+1跳过一个整型,也就是4个字节。所以结果是0x100004。


  • 验证:


3.3笔试题三

int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;


注意看,数组初始化时用的是小括号,所以数组只存放了1 3 5
a[0]是第一行的数组名,就是第一行首元素的地址。就是1的地址
p[0]==*(p+0)==星号p。所以结果应该是1.


  • 验证:


3.4笔试题四

//假设环境是x86环境,程序输出的结果是啥?
#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;
}


这里我写了思路图解,具体讲解看图就可以了。

  • 验证:

在这里插入图片描述


3.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));printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}

  • &aa
    &数组名,是整个二维数组的地址,+1跳过整个二维数组。指向二维数组后面的地址。
    转化为整形指针后,-1向后移动一个整型,指向10.(ptr2-2)
  • aa
    aa是数组名,是第一个一维数组的地址,+1跳过一个一维数组,指向第二个 一维数组的首元素。强制转化为整形指针,-1向后移动一个整型,指向5.(ptr1-1)

  • 验证:


3.6笔试题六

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

看名字就知道这是一道阿里巴巴的题目。
小伙伴们要竖起耳朵好好听啦!

a是一个指针数组,三个指针分别指向三个字符串。
pa是一个二级指针,指向指针数组首元素a.
pa++跳过一个char*类型的元素,就是一个字符指针。
指向数组第二个元素,*pa就拿到的哥字符串的指针,就是地址。
所以输出的是at。


  • 验证:


3.7笔试题七

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

这道题有点难,大家一定要跟上小编的思路,图文结合来看。

  1. 输出一:

    这里大家图文结合看就好了。

  2. 输出二:

  3. 输出三:

  4. 输出四:


3.8验证


后言

今天给大家带来的指针练习,还是有点难度的。但是只要我们记好那几个关键的知识点,一步一步解题,就没有那么难了。回去大家好好消化一下。到这里,我们就是一个指针高手啦!今天就分享到这里,咱们下期见!拜拜~

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

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

相关文章

OneFlow深度学习简介

介绍 OneFlow是一个基于深度学习的开源框架,主要面向机器学习工程师和研究人员。它提供了类似于其他深度学习框架(如TensorFlow和PyTorch)的API,同时具有高性能和高效的特点。OneFlow专注于在大规模数据集和分布式环境下的训练和推理,以及在生产环境中的部署和优化。其设计…

HBuilderX 中开发vue,引入百度地图获取当前ip地址定位

实现功能&#xff1a;使用百度地图获取IP地址&#xff0c;定位到当前位置 参考文档地址&#xff1a;MapVGL | 快速入门 一、在有外网的情况下&#xff0c;常规引入百度地图的方法如下&#xff1a; 1、在index.html中引入 <script src"//api.map.baidu.com/api?v1.…

Python100个库分享第14个—plyfile(将ply文件展示3d模型)

目录 专栏导读库的介绍库的安装ply文件格式介绍ply下载网址&#xff08;是斯坦福大学的3d模型下载网址&#xff09;报错解决完整代码参考&#xff1a;总结 专栏导读 &#x1f338; 欢迎来到Python办公自动化专栏—Python处理办公问题&#xff0c;解放您的双手 &#x1f3f3;️…

C语言单链表详解

链表和顺序表的区别 顺序表的底层存储空间是连续的&#xff0c;链表的底层存储空间是不连续的&#xff0c;链表的每个节点需要额外的指针来指向下一个节点&#xff0c;占用更多的存储空间。 顺序表的随机访问性能好&#xff0c;时间复杂度为O(1)&#xff0c;链表的随机访问性能…

接口优化技巧

一、背景 针对老项目&#xff0c;去年做了许多降本增效的事情&#xff0c;其中发现最多的就是接口耗时过长的问题&#xff0c;就集中搞了一次接口性能优化。本文将给小伙伴们分享一下接口优化的通用方案 二、接口优化方案总结 1.批处理 批量思想&#xff1a;批量操作数据库&a…

python怎么输出小数

先将整型转换成float型&#xff0c;再进行计算&#xff0c;结果就有小数了。 >>> a 10 >>> b 4 >>> c a/b >>> a,b,c (10, 4, 2) >>> a float(a) >>> d a/b >>> a,b,d (10.0, 4, 2.5) >>> 注意&…

螺栓拧紧工具选择——SunTorque智能扭矩系统

智能扭矩系统-智能拧紧系统-扭矩自动控制系统-SunTorque 螺栓拧紧工具的选择遵循以下几点&#xff1a; &#xff08;1&#xff09;工艺要求精度。目前拧紧工具有两大类&#xff1a;一类是气动拧紧&#xff1b;另一类是电动拧紧&#xff0c;前者精度较后者精度低&#xff0c;发…

从HashMap了解二叉树、平衡二叉树、红黑树

前言 面试过程中&#xff0c;多多少少会问一点数据结构&#xff08;二叉树&#xff09;的问题&#xff0c;今天我们来复习一下二叉树的相关问题&#xff0c;文末总结。 1. 二叉树的由来 在 jdk1.8 之前&#xff0c;HashMap 的数据结构由「数组链表」组成&#xff0c;数组是 Ha…

免费插件集-illustrator插件-Ai插件-批量替换链接图

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;进行批量替换链接图。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/87890501&am…

SAP NACE V1 销售订单打印配置

在项目上&#xff0c;经常会有一些打印的需求&#xff0c;实现的形式也是五花八门&#xff0c; 有通过写一个打印程序&#xff0c;集成所有打印的&#xff0c;也有通过配置NACE 来完成标准打印输出的 今天我们来记录一下&#xff0c;如何通过NACE 的配置一个标准销售订单的打…

【C++软件调试技术】C++软件开发维护过程中典型调试问题的解答与总结

目录 1、引发C软件异常的常见原因有哪些&#xff1f; 2、排查C软件异常的常用方法有哪些&#xff1f; 3、为什么要熟悉常见的异常内存地址&#xff1f; 4、调试时遇到调用IsBadReadPtr或者IsBadWritePtr引发的异常&#xff0c;该如何处理&#xff1f; 5、如何排查GDI对象泄…

openstack安装dashboard后登录网页显示404错误

1. 2.进入该目录vim /etc/httpd/conf.d/openstack-dashboard.conf 增加这一行 WSGIApplicationGroup %{GLOBAL} 重启httpd后就可以访问了

如何在Windows使用固定公网地址SSH远程访问本地Archcraft系统

文章目录 1. 本地SSH连接测试2. Archcraft安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接小结 5. 固定SSH公网地址6. SSH固定地址连接 Archcraft是一个基于Arch Linux的Linux发行版&#xff0c;它使用最简主义的窗口管理器而不是功能齐全的桌面环境来提供图形化用户界面。 C…

使用SpeechRecognition和vosk处理ASR

SpeechRecognition可以支持多种模型语音转文字&#xff0c;感觉vosk还不错&#xff0c;使用起来也简单一些&#xff1b;百度也有PaddleSpeech&#xff0c;但是安装起来太麻烦&#xff0c;不是这个库版本不对就是那个库有问题&#xff0c;用起来不方便&#xff1b; 安装SpeechR…

【Git教程】(十)版本库之间的依赖 —— 项目与子模块之间的依赖、与子树之间的依赖 ~

Git教程 版本库之间的依赖 1️⃣ 与子模块之间的依赖2️⃣ 与子树之间的依赖&#x1f33e; 总结 在 Git 中&#xff0c;版本库是发行单位&#xff0c;代表的是一个版本&#xff0c;而分支或标签则只能被创建在版本库这个整体中。如果一个项目中包含了若干个子项目&#xff0c;…

12.文件浏览器

子程序参数的使用 1.可空的用法&#xff1b;表示这个参数不写也行。 2.如何使用递归 3.需要注意的事 递归的子程序必须有个退出的条件 注意区分递归和循环&#xff0c;不要混用 流程&#xff1a; 1.插入按钮&#xff0c;输入输出调试文本&#xff08;“按钮被单击”&…

2024年主流的java混淆工具有哪些

2024年&#xff0c;主流的Java混淆工具可能会包括&#xff1a; ProGuard&#xff1a;ProGuard 是一个免费的开源 Java 混淆工具&#xff0c;可用于压缩、优化和混淆 Java 字节码。它是Android开发者的首选混淆工具之一&#xff0c;并且在Java应用程序中也得到了广泛应用。 Dex…

Windows本地部署Ollama+qwen本地大语言模型Web交互界面并实现公网访问

文章目录 前言1. 运行Ollama2. 安装Open WebUI2.1 在Windows系统安装Docker2.2 使用Docker部署Open WebUI 3. 安装内网穿透工具4. 创建固定公网地址 前言 本文主要介绍如何在Windows系统快速部署Ollama开源大语言模型运行工具&#xff0c;并安装Open WebUI结合cpolar内网穿透软…

OpenCV4.9图像金字塔

目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 pyrUp()和 pyrDown()对给定图像进行下采样或上采样。 理论 注意 下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书。 通常&#xff0c;我们需要将图像转换为与原始图像不同的大小。为此…

Linux 1.文件编程(dup、dup2)

重定向 重定向是什么&#xff1f;dupdup2 重定向是什么&#xff1f; 进程在最开始运行的时候&#xff0c;首先打开了三个文件&#xff0c;分别是标准输入流、标准输出流、标准错误输出流。证明的时候我是把标准输出留给关闭了&#xff0c;然后紧接着创建的文件就会占用已关闭的…