当前位置: 首页 > news >正文

深入理解:指针变量的解引用 与 加法运算

前言

        指针变量的解引用和加法运算是非常高频的考点,也是难点,因为对初学者的不友好,这就导致了各大考试都很喜欢在这里出题,通常会伴随着强制类型转换、二维数组、数组指针等一起考查大家对指针的理解。但是不要怕,也许看完这篇文章你有了新的认识和理解,写的不透彻的地方也希望大家多多指正

理解:指针变量的解引用

我们分下面两步理解:

  1. 解引用,拿出来的是什么
  2. 解引用,根据什么拿出来的

1. 拿出来的是什么

        首先解引用拿出来的就是指针指向的内容,比如指针p指向的是这个地址,*p就是拿出来地址里面的内容;

2. 根据什么拿出来的

        指针的类型决定了,对指针解引用的时候有多大的权限(能拿出几个字节)。
比如: char* 的指针解引用就只能访问1字节
#include <stdio.h>
int main()
{int a = 40000;int *p = &a;printf("%d\n", *(char*)p);return 0;
}

本应该是40000的值,咋变成64了?这其实就跟解引用的指针类型有关了,但是这里还涉及了一个知识点是大小端,上面是小端的结果,小端就是低位在低地址,高位在高地址;大端反之,所以会有不同的结果;因为解引用是从低地址开始的;大端结果就应该是0

int* 的指针的解引用就能访问4字节
#include <stdio.h>
int main()
{int a = 40000;int *p = &a;printf("%d\n", *p);return 0;
}

所以这里就是直接解引用了4个字节,只要是涉及多个字节了,取出来的要按照低位还是低位来算,切记不能以为先取出来的就是高位;

理解:指针变量的加法

我们来分这两步理解:

  1. 指针变量的加法,加的是什么
  2. 指针变量的加法,是根据什么来加的

1. 加的是什么

        我们首先来分析指针变量是什么,指针变量是一个地址,那指针变量的加法,实际上就是对这个指针变量代表的地址做加法,也就是向后移动指针变量指向的位置,让指向的地址更高。

2. 根据什么来加

        指针变量的加法是根据:指针变量的数据类型实现的;

指针 + n = 指针 + n*指针类型中的除*的类型所占字节

char*就是n

int*就是4n

比如:char*类型

char c = 0;
char *pc = &c;
printf("pc = %p\n", pc);
printf("pc + 1 = %p\n", pc + 1);

我们可以看到pc+1的值向后移动了1个字节

比如:int*类型

int i = 0;
int *pi = &i;
printf("  pi = %p\n", pi);
printf("pi+1 = %p\n", pi + 1);

此时int类型的pi+1的值是向后移动了4个字节

比如:double*类型

double d = 0;
double *pd = &d;
printf("  pd = %p\n", pd);
printf("pd+1 = %p\n", pd + 1);

此时double类型的pd+1的值是向后移动了8个字节

例题

1. 普通的加法

#include <stdio.h>
int main()
{int arr[5] = {1, 2, 3, 4, 5};int *p = arr;printf("%d\n", *(p + 1));printf("%d\n", p[1]);return 0;
}

答案及解析:2 2

首先p指向的是arr,arr是数组名,代表的是首元素的地址,所以p指向的就是首元素的地址

p数据类型为int*,p+1就是向后移动4*1个字节,到达arr[1]的地址,解引用是取4个字节,取到的就是arr[1];

p既然是首元素地址,那p和arr就没区别,所以p[1] 等价于 arr[1],为2;

2. 包含强制类型转换的加法

#include <stdio.h>
int main()
{int arr[5] = {1, 2, 3, 4, 5};int *p = arr;printf("%d\n", *((char*)p + 1));printf("%d\n", *((short*)p + 2));return 0;
}

答案及解析:0 2

这时候我们必须要用二进制来表示数字,因为这里涉及到了强制类型转换;此时加法和解引用都会受到影响。所以这里的第一个输出语句,是先强制类型转换成char*类型,然后一直是对char*类型的指针进行加法和解引用,这里我一直按小端讲解

而我们的第二个输出语句则是强制转换short*,加法和解引用都是2字节

3. 包含二维数组和数组指针的加法


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

在这里首先要知道二维数组名代表的是什么,我们必须清楚一个逻辑

二维数组是一维数组的数组,也就是说可以把二维数组看成存放一维数组的数组;

这样说肯定很抽象,我们看图:

二维数组名代表的是第一行的地址,也就是代表整个第一行,相当于&arr[0],那二维数组名就是一个数组指针了,因为数组指针也是表示的一个数组的地址;所以我们可以定义一个数组指针p = arr;那p + 1,就要慎重了,p的数据类型是int (*)[2],所以p+1,就是移动整个数组的大小,所以p+1 就指向的是arr[1]这个数组,p + 1 = &arr[1],所以解引用一次就是取到了整个数组arr[1],但是*(p + 1) = arr[1],arr[1]是这个二维数组的行,相当于该行这个一维数组的数组名,既然是一维数组的数组名,就是首元素地址,那就是int*类型,再解引用就是解引用4字节,拿到的就是3.

相关文章:

深入理解:指针变量的解引用 与 加法运算

前言 指针变量的解引用和加法运算是非常高频的考点&#xff0c;也是难点&#xff0c;因为对初学者的不友好&#xff0c;这就导致了各大考试都很喜欢在这里出题&#xff0c;通常会伴随着强制类型转换、二维数组、数组指针等一起考查大家对指针的理解。但是不要怕&#xff0c;也许…...

Docker 镜像构建的最佳做法

一、镜像分层 使用docker image history命令&#xff0c;可以看到用于在镜像中创建每个层的命令。 1、 使用docker image history命令查看创建的入门镜像中的层。 docker image history getting-started 您应该得到如下所示的输出&#xff1a; IMAGE CREATED…...

工作上Redis安装及配置

下载redis软件 第一步&#xff1a;解压压缩包 tar -zxvf redis-7.0.14.tar.gz 第二步&#xff1a;移动redis存放目录&#xff08;结合个人需求而定&#xff01;&#xff09; redis-7.0.14&#xff1a;解压后的文件路径 /usr/local&#xff1a;移动后的文件路径 mv redis-7.0.…...

电商项目之Web实时消息推送(附源码)

文章目录 1 问题背景2 前言3 什么是消息推送4 短轮询5 长轮询5.1 demo代码 6 iframe流6.1 demo代码 7 SSE7.1 demo代码7.2 生产环境的应用 &#xff08;重要&#xff09; 8 MQTT 1 问题背景 扩宽自己的知识广度&#xff0c;研究一下web实时消息推送 2 前言 文章参考自Web 实时消…...

上机实验四 哈希表设计 西安石油大学数据结构

实验名称&#xff1a;哈希表设计 &#xff08;1&#xff09;实验目的&#xff1a;掌握哈希表的设计方法及其冲突解决方法。 &#xff08;2&#xff09;主要内容&#xff1a; 已知一个含有10个学生信息的数据表&#xff0c;关键字为学生“姓名”的拼音&#xff0c;给出此表的一…...

Ubuntu22.04 交叉编译mp4V2 for Rv1106

一、配置工具链环境 sudo vim ~/.bashrc在文件最后添加 export PATH$PATH:/opt/arm-rockchip830-linux-uclibcgnueabihf/bin 保存&#xff0c;重启机器 二、下载mp4v2 下载路径&#xff1a;MP4v2 | mp4v2 三、修改CMakeLists.txt 四、执行编译 mkdir build cd buildcmak…...

缓存穿透、击穿、雪崩

缓存穿透&#xff1a; 指的是恶意用户或攻击者通过请求不存在于缓存和后端存储中的数据来使得所有请求都落到后端存储上&#xff0c;导致系统瘫痪。 解决方案&#xff1a; 通常包括使用布隆过滤器或者黑白名单等方式来过滤掉无效请求&#xff0c;以及在应用程序中加入缓存预热…...

(1w字一篇理解透Unsafe类)Java魔法类:Unsafe详解

Java魔法类 Unsafe 文章导读&#xff1a;(约12015字&#xff0c;阅读时间大约1小时)1. Unsafe介绍2. Unsafe创建3. Unsafe功能3.1内存操作3.2 内存屏障3.3 对象操作3.4 数组操作3.5 CAS操作3.6 线程调度3.7 Class操作3.8 系统信息 4. 总结 JUC源码中的并发工具类出现过很多次 …...

Python的正则表达式使用

Python的正则表达式使用 定义使用场景查替换分割 常用的正则表达符号查原字符英文状态的句号点 .反斜杠 \英文的[]英文的()英文的?加号 星号 *英文状态的大括号 {} 案例 定义 正则表达式是指专门用于描述或刻画字符串内在规律的表达式。 使用场景 无法通过切片&#xff0c;…...

Elasticsearch:评估 RAG - 指标之旅

作者&#xff1a;Quentin Herreros&#xff0c;Thomas Veasey&#xff0c;Thanos Papaoikonomou 2020年&#xff0c;Meta发表了一篇题为 “知识密集型NLP任务的检索增强生成” 的论文。 本文介绍了一种通过利用外部数据库将语言模型 (LLM) 知识扩展到初始训练数据之外的方法。 …...

【2023.12.4练习】数据库知识点复习测试

概论 数据表&#xff1a;用于存储现实中数据的联系。 储存信息联系。 字段&#xff1a;又称列&#xff0c;如姓名、年龄、编号等。 记录&#xff1a;又称元组&#xff0c;为数据表中的一行&#xff0c;代表了一个实体的信息。 数据库&#xff08;DB&#xff09;&#xff1…...

【wvp】测试记录

ffmpeg 这是个莫名其妙的报错&#xff0c;通过排查&#xff0c;应该是zlm哪个进程引起的 会议室的性能 网络IO也就20M...

【若依框架实现上传文件组件】

若依框架中只有个人中心有上传图片组件&#xff0c;但是这个组件不适用于el-dialog中的el-form表单页面 于是通过elementui重新写了一个上传组件&#xff0c;如图是实现效果 vue代码 <el-dialog :title"title" v-model"find" width"600px"…...

玩转大数据5:构建可扩展的大数据架构

1. 引言 随着数字化时代的到来&#xff0c;大数据已经成为企业、组织和个人关注的焦点。大数据架构作为大数据应用的核心组成部分&#xff0c;对于企业的数字化转型和信息化建设至关重要。我们将探讨大数据架构的基本要素和原则&#xff0c;以及Java在大数据架构中的角色&…...

【华为数据之道学习笔记】非数字原生企业的特点

非数字原生企业的数字化转型挑战 软件和数据平台为核心的数字世界入口&#xff0c;便捷地获取和存储了大量的数据&#xff0c;并开始尝试通过机器学习等人工智能技术分析这些数据&#xff0c;以便更好地理解用户需求&#xff0c;增强数字化创新能力。部分数字原生企业引领着云计…...

Kubernetes学习笔记-Part.01 Kubernets与docker

目录 Part.01 Kubernets与docker Part.02 Docker版本 Part.03 Kubernetes原理 Part.04 资源规划 Part.05 基础环境准备 Part.06 Docker安装 Part.07 Harbor搭建 Part.08 K8s环境安装 Part.09 K8s集群构建 Part.10 容器回退 第一章 Kubernets与docker Docker是一种轻量级的容器…...

k8s学习

文章目录 前言一、k8s部署方式二、学习k8s的方式今天主要配置k8s环境的方式今天遇到的是一个在k8s进行初始化的方式&#xff0c;但是发现k8s不能正常初始化总是出现错误&#xff0c;或者在错误中有问题的方式&#xff0c;在网上查询挺多资料需要重新启动kub文件&#xff0c;删除…...

测试:JMeter和LoadRunner比较

比较 JMeter和LoadRunner是两款常用的软件性能测试工具&#xff0c;它们在功能和性能上有一定的相似性和差异。下面从几个方面对它们进行比较&#xff1a; 1. 架构和原理&#xff1a; JMeter和LoadRunner的架构和原理基本相同&#xff0c;都是通过中间代理监控和收集并发客户…...

(C语言)通过循环按行顺序为一个矩阵赋予1,3,5,7,9,等奇数,然后输出矩阵左下角的值。

#include<stdio.h> int main() {int a[5][5];int n 1;for(int i 0;i < 5;i ){for(int j 0;j < 5;j ){a[i][j] n;n 2;}}for(int i 0;i < 5;i ){for(int j 0;j < i;j )printf("%-5d",a[i][j]);printf("\n");}return 0; } 运行截图…...

GitHub项目推荐-Deoldify

有小伙伴推荐了一个老照片上色的GitHub项目&#xff0c;看了简介&#xff0c;还不错&#xff0c;推荐给大家。 项目地址 GitHub - SpenserCai/sd-webui-deoldify: DeOldify for Stable Diffusion WebUI&#xff1a;This is an extension for StableDiffusions AUTOMATIC1111 w…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...