C语言:深入理解指针(1)

1. 内存和地址

  在了解指针前,我们需要知道内存和地址是什么。

1.1 内存

       首先来看内存。举个例子:当你在酒店找房间时,你并不是一层一层一间一间找,而是通过酒店为每间房子设置的门牌号直接找到你的房间,这样的效率就会快很多。

       把上面的例子投影到计算机中:CPU在处理数据的时候,需要在内存中取数据,处理后的数据又会放回到内存中。内存空间管理时就会把内存划分为一个个内存单元,每个内存单元大小设置为一字节。每个内存单元也有其相应的编号,这样CPU就可以通过编号快速找到一个内存单元。这个编号在计算机中我们称它为地址。C语言中给地址起了个新的名字,叫指针。因此我们可以理解为:内存单元的编号==地址==指针

1.2 如何理解编址

       首先,需要知道,计算机内部是有很多硬件单元的,各个硬件单元相互工作时是通过“线”连接起来的。而CPU和内存之间也是有⼤量的数据交互的,所 以,两者必须也⽤线连起来。我们今天只关心地址总线(还有数据总线和控制总线)。当CPU在访问某个内存单元时,必须知道该内存单元在哪个位置,因此需要给每个内存单元进行编址。

       计算机中的编址,并不是把每个字节的地址记录 下来,⽽是通过硬件设计完成的。就像吉他和钢琴等乐器一样,琴弦和钢琴键上并没有标注 do、re、mi......。但是演奏者总能精准地找到在什么位置,这是大家约定俗成的。

       硬件编制也是如此,32位机器就有32根地址总线,每一位都有 0 和 1 两种结果,32根像就能表示出 2 的 32 次方种结果,每一种排列都表示一个地址,64位机器以此类推。地址信息被下达给内存,在内存上,就可以找到 该地址对应的数据,将数据在通过数据总线传⼊ CPU内寄存器。

2.指针变量和地址

2.1 取地址操作符(&)

       在C语言中创建变量的本质就是向内存申请空间。如图:

        右下角的内存中 & 为取地址操作符,图中为取出 x 的地址,是一个单目操作符。我们之前学的 a&b 表示 a 按位与 b ,两者不一样。上述代码就是创建了一个整型变量 x ,在内存中申请了 4 个字节用来存放 4。当我们打印 x 的地址时,就会发现这个内存单元中正好存放的是 4。

2.2 指针变量和解引用操作符

2.2.1指针变量

        我们通过取地址操作符(&)得到一个变量的地址,我们通过指针变量将它存放起来,便于使用例如:

#include <stdio.h>
int main()
{int x = 4;int * p = &x;//取出x的地址放到指针变量p中return 0;
}

        指针变量也是一种变量,只不过让它是用来存放地址的,变量中的值都是地址。

2.2.2 如何理解指针变量

        刚刚的定义的 int * p 中,* 说明 p 是一个指针变量,int 表示 p 指向的的类型是整型。同理如果有个 char、double、等类型的变量,他们的地址就要分别放在 char*、double* 中。

2.2.3 解引用操作符

        我们将地址存起来肯定是要使用的,使用时我们就会用到解引用操作符(*)。

        上图中就使用了解引用操作符我们通过 *p 找到了 x 并且修改了 x 的值,我们修改时并没有写 x = 0 ,而是直接通过指针变量来修改,即 *p=0 ,这样写代码时会更加灵活。

2.3 指针变量的大小

        32位机器有32根地址总线,那么它就需要 4 个字节来存储地址(1个字节 8 个比特位,4个字节刚好 32 个比特位),同理 64 位机器则需要 8 个字节来存储地址。同时我们要注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。不管指针变量是  char 还是 int ,他们在32位机器下都是 4 个字节,在 64 位机器下都是 8 个字节。

3.指针变量类型的意义

3.1指针的解引用

        让我们来对比下面两段代码:

         我们发现 int* 和 char* 修改的字节不同,因此:指针的类型决定了对指针解引用的时候有多大的权限(⼀次能操作⼏个字节)。 ⽐如 char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引⽤就能访问四个字节。

3.2 指针+-整数

        同样的,对指针+-时,不同的指针变量的类型所移动的距离也不同。若对 int* 进行+/-1时,会一次移动四个字节,而对 char* 进行+/-1时则一次移动一个字节。

3.3 void*指针

         void* 表示无具体类型的指针。这种类型的指针可以接受任意类型的地址,但是我们不能直接对这种类型的指针进行+/-整数和对指针的解引用,需要进行强制类型转换。⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果。使得⼀个函数来处理多种类型的数据。

4.指针运算

4.1 指针+-整数

        数组在内存中是连续存放的,因此只要知道第⼀个元素的地址后,我们可以通过加减操作来获取后面的所有元素。

4.2 指针-指针

        

       由图可得,指针-指针所得带的结果是两个指针之间的元素个数,但前提是这两个指针指向的是同一块内存空间。

       另外,指针也能进行关系运算。

        

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

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

相关文章

完整的 SquareStudio 注册登录功能实现方案:已经烧录到开发板正常使用

根据你的需求&#xff0c;我将提供完整的实现方案&#xff0c;解决按钮同时执行多个动作的问题&#xff0c;并确保注册登录功能正常工作。所需文件结构需要创建和修改的文件如下&#xff1a;ui_events.h - 事件处理函数声明events.c - 实际的事件处理逻辑ui.c - UI 初始化和事件…

OkHttp 与 Chuck 结合使用:优雅的 Android 网络请求调试方案

前言在 Android 应用开发过程中&#xff0c;网络请求调试是日常工作中不可或缺的一部分。Chuck 是一个轻量级的 OkHttp 拦截器&#xff0c;能够在应用内直接显示网络请求和响应的详细信息&#xff0c;无需连接电脑或使用额外工具。本文将详细介绍如何将 OkHttp 与 Chuck 结合使…

AI学习--本地部署ollama

AI小白&#xff0c;记录下本地部署ollama1.下载安装ollama下载地址ollama官方地址https://ollama.com/download根据系统下载即可下面是我下载的地址 https://release-assets.githubusercontent.com/github-production-release-asset/658928958/e8384a9d-8b1e-4742-9400-7a0ce2a…

docker 设置镜像仓库代理

1. 创建 Docker 服务的代理配置文件sudo mkdir -p /etc/systemd/system/docker.service.d2.创建文件 /etc/systemd/system/docker.service.d/http-proxy.conf&#xff0c;内容如下&#xff1a;[Service] Environment"HTTP_PROXYhttp://192.168.0.111:7890" Environme…

ffmpeg rtsp 丢包处理

直接用 demux 在有些网络中&#xff0c;丢包画屏&#xff1b; 再ffmpeg和ffplay中&#xff0c;可以指定 tcp 方式&#xff0c;所以代码直接设置陶瓷坯方式&#xff1b; // 设置RTSP选项优化接收数据流防止数据包丢失 av_dict_set(&options, "rtsp_transport", …

aosp15实现SurfaceFlinger的dump输出带上Layer详细信息踩坑笔记

背景&#xff1a; 针对上一篇文章 aosp15上SurfaceFlinger的dump部分新特性-无Layer信息输出如何解决&#xff1f; 给大家布置了一个小作业&#xff0c;那就是需要实现dumpsys SurfaceFlinger相关输出中可以携带上所有的Layer的详细信息需求&#xff0c;今天来带大家详细实现一…

Linux 网络调优指南:废弃的 tcp_tw_recycle 与安全替代方案

一、问题起源:消失的内核参数 当你在 Debian 10 系统执行 sysctl 命令时,若看到报错: sysctl: cannot stat /proc/sys/net/ipv4/tcp_tw_recycle: 没有那个文件或目录 这并非配置错误,而是Linux 内核演进的结果。自 4.12 版本起,内核正式移除了 tcp_tw_recycle 参数——…

删除有序数组中的重复项

class Solution {public int removeElement(int[] nums, int val) {// 暴力法int n nums.length;for (int i 0; i < n; i) {if (nums[i] val) {for (int j i 1; j < n; j) {nums[j - 1] nums[j];}i--;n--;}}return n;} }代码逻辑解析首先获取数组长度n&#xff0c;…

【Pytest】从配置到固件的使用指南

掌握高效测试的关键技巧&#xff0c;打造专业级自动化测试框架一、Pytest框架的核心优势 Pytest作为Python最强大的测试框架之一&#xff0c;以其简洁灵活的语法和丰富的扩展能力深受开发者喜爱。相比unittest&#xff0c;Pytest提供了更直观的测试编写方式和更强大的功能集&am…

[matlab]matlab上安装xgboost安装教程简单版

【前言】 网上基于MATLAB的xgboost安装教程太少了&#xff0c;以至于几乎搜不到&#xff0c;为此做了一个简单安装教程【安装前提】 有matlab软件&#xff0c;版本越高越好&#xff0c;我用的是2023a。理论支持matlab2018a及其以上&#xff0c;因此需要自己提前安装好matlab【安…

基于多种机器学习的成都市二手房房价分析与价格预测【城市可换、算法模型多种对比】

文章目录有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目背景数据来源与采集方式数据预处理与清洗流程探索性数据分析&#xff08;EDA&#xff09;模型构建与预测方法项目意义与应用前景相关可视化展示总结每文一语有需要本项目的代码或文档以及…

PostgreSQL 事务ID环绕问题

事务ID&#xff08;XID&#xff09;基本概念 从Transactions and Identifiers可知&#xff1a; 事务 ID&#xff0c;例如 278394&#xff0c;会根据 PostgreSQL 集群内所有数据库使用的全局计数器按顺序分配给事务。此分配会在事务首次写入数据库时进行。这意味着编号较低的 x…

高等数学-矩阵知识

好的&#xff0c;我们来详细讲解高等数学&#xff08;主要是线性代数部分&#xff09;中的核心矩阵知识。矩阵是线性代数的基石&#xff0c;广泛应用于数学、物理、工程、计算机科学、经济学等众多领域。 一、矩阵的基本概念定义&#xff1a; 一个 m n 矩阵 (Matrix) 是一个由…

React 项目性能优化概要

应用级性能优化&#xff0c;需要结合实际需求展开分析&#xff0c;通常我们需要从以下几个方面来考虑&#xff1a; 1. 识别性能瓶颈 识别性能瓶颈是优化的第一步&#xff0c;通过各种工具和方法找到影响性能的主要原因&#xff1a; React Profiler&#xff1a;使用 React Dev…

【web自动化】-5- fixture集中管理和项目重构

一、投标用例设计 # 定义让前台页面保持自动登录的fixture pytest.fixture() def user_driver():driver webdriver.Chrome()driver.get("http://47.107.116.139/fangwei/")driver.maximize_window()# 创建页面类对象page ReceptionLoginPage(driver)# 通过页面类对…

Dify工作流:爬虫文章到AI知识库

部署Dify 代码拉取 git clone https://github.com/langgenius/dify.git cd dify/docker启动容器 docker-compose up -d启动成功准备知识库 创建知识库 创建一个空的知识库要先从网址中&#xff0c;找到这个知识库的id&#xff0c;记下后面需要用到。新建API密钥 创建密钥&#…

支付鉴权方案介绍

前后端交互中的鉴权是确保请求来源合法、身份可信、权限合适的关键手段。不同系统架构和业务类型下,使用的鉴权方式略有不同,但主要可分为以下几类: ✅ 一、前后端交互常见的鉴权方式概览 鉴权方式 优点 缺点 适用场景 Cookie + Session 简单、成熟,服务端易控制 不适合跨域…

halcon处理灰度能量图

使用halcon处理射线图像&#xff0c;对高能区域和低能区域分割处理感兴趣区域&#xff0c;筛选区域下的灰度值区间范围。图像灰度值为16位深度图。* 读取灰度图像 read_image (Image, /123.tif)** 获取图像尺寸 get_image_size (Image, Width, Height)* 分割图像为左右两部分&a…

Oracle From查看弹性域设置

打开弹性与设置&#xff1a;【应用开发员->弹性域->说明性->段】打开后界面如下&#xff1a; 把光标定位到标题&#xff0c;然后点击“手电筒”搜索名称&#xff08;名称就是你要查询的那个弹性域的名称&#xff09;我这里就是搜索“附加题头信息”&#xff0…

git初始流程

对于一个新项目&#xff0c;从 Git 仓库拉取 test_tool 分支并进行后续修改提交的完整流程如下&#xff1a; 一、首次拉取项目&#xff08;克隆仓库并切换分支&#xff09;克隆远程仓库到本地 打开终端&#xff08;或 PyCharm 的 Terminal&#xff09;&#xff0c;进入你想存放…