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

C/C++指针

指针(pointer)是C/C++语言中的一种数据类型。指针与int、char等数据类型相似,都是在内存中开辟相应类型的数据区域使用,不同的是int存储的是整数值,而指针存储的是内存地址。指针是在内存中开辟指针类型的区域存储内存地址,通过指针存储的内存地址找到对应内存区域的值。简单讲就是通过一个内存地址找到另一个内存地址的值。虽然指针都是用来存储内存地址,但是在定义指针时要明确指针指向的内存区域的类型,比如int*整数型指针指向整数型地址,char*字符型指针指向字符型地址,void*无类型指针指向任何类型地址,void*指针指向的内容可以转换为任何类型的值。

一、什么是内存地址

指针是用来存储内存地址的数据类型,那么内存地址是什么?计算机软件在运行过程中使用内存进行数据存储,操作系统开辟的每一块内存区域都有相应的内存地址,每块内存区域又可以存储不同的数据,计算机通过内存地址来读取和写入内存区域的数据。当然开辟内存区域存储的内容为何类型,是整数还是字符串需要在定义时明确。

二、指针运算符

(一)运算符*

*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在定义时表示定义和初始化,在定义和初始化后表示所指向的变量。

int myValue;
// 这里的*pint表示定义
int *pint = &myValue;
// 这里的*pint实际上就是myValue
*pint = 6;

(二)运算符&

&是单目运算符,其结合性为自右至左,功能是取变量的地址。任何在内存中开辟的区域都可以通过&来获取地址,可以是变量、常量、指针。

// 变量地址
int myValue;
int *pint = &myValue;// 指针地址
int **newPint = &pint;
// 赋值myValue为6
**newPint = 6;// 常量地址
const int myValue1 = 10;
const int *pint1 = &myValue1;
内存区域:变量
内存地址
名称
类型
内存区域:一级指针
内存地址
名称
类型
内存区域:二级指针
内存地址
名称
类型
指向
指向
6
int
myValue
0x325658
0x325658
int*
pint
0x3848921
0x3848921
int**
newPint
0x3256567

三、指针定义与初始化

指针与普通的常量变量一样,使用前需要先定义,意思是让操作系统开辟内存区域。指针定义后必须立即初始化,否则编译将会报错。初始化可以赋值某个内存地址,当不确定目标类型时可以初始化为空指针。

(一)初始化内存地址

int myValue;
int *pint = &myValue;
// 变量与指针同时定义
int myValue, *pint = &myValue;

指针指向的地址必须与目标地址的数据类型一致,如指针时int类型,指向的地址也必须时int类型,反之为非法赋值。

(二)初始化为常量

// 合法,表示pint指针指向一个无名字符串常量的地址,里面存放的数据是字符数组abc,
// 指针初始化为数组不需要&运算符,自动指向数组首地址。
char * pint = "abc";
// 非法
*pint = "def";

初始化指针时赋值字符串,表示在内存中开辟区域,并把首地址存储到pint指针中,指针指向地址为常量不可更改。

(三)初始化为数组

int ages[20];
int *pint = ages;
// 变量与指针同时定义
double readings[50], *marker = readings;

数组不需要&寻址符,赋值时将会把数组首地址赋值给指针。

指针指向数组项

int ages[20];
// 指针指向ages数组索引5的子项
int *pint = &ages[5];

指针指向数组项时需要使用&运算符。

(四)初始化空指针

1.空指针0

因为指针定义后必须赋值初始化,当未确定指针存放的地址时,可以赋值为0初始化为空指针。

int *ptrToint = 0;
double *ptrToDouble = 0;

0表示分配给当前未指向一个有效内存位置的指针,用户程序不能访问地址为 0 的内存,因为它被操作系统数据占用,这使得 0 成为指示无效内存位置值的安全选择。

2.空指针NULL

某些头文件(如iostream、fstream 、 cstdlib)定义了NULL常量为0地址,当程序包含这些头文件时只需要赋值NULL给指针即可定义空指针。

int *ptrToint = NULL;
float *ptrTofloat = NULL;

3.空指针nullptr

C++11 定义了关键字 nullptr 来指示一个无效的内存地址

int *ptrToint = nullptr;
double *ptrToDouble = nullptr;

4.空指针的判断

指针在使用前可以先判断是否为空指针。

if (p != nullptr) { // 使用指针 P... }
if (p != NULL) { // 使用指针 P"... }
if (p != 0) { // 使用指针 P... }
// 等同于
if (p) { // 使用指针 P... }

四、指针的常量定义

指针的常量有指针常量、常量指针两种,区别在于定义时指针前有无修饰符const。因为指针是内存地址的指向,两种常量涉及到指针本身和指向地址的修改关系,因此指针本身和指向地址到底哪个不可更改很容易混淆。可以理解为定义指针时在*(指针)之后有const为指针常量,之前则为常量指针。另外还有一种*前后都有const,表示指向常量的指针常量。

(一)指针常量

指针常量int * const指针本身是常量不可变,指向地址可以是常量也可以是变量。

1.指向“变量”的指针常量

int myValue;
int newValue;
// 指向“变量”的指针常量,
int * const pint = &myValue;
// 非法
pint = &newValue;
// 合法
*pint = 6;

指针int *前无const修饰符,指针指向地址为int类型,指针本身不可修改,指向的int类型变量可修改。

2.指向“常量”的指针常量

指向的地址是常量,”指针常量“前应加const修饰符,即const int * const

const int myValue = 10;
const int newValue = 20;
// 指向“常量”的指针常量
const int * const pint = &myValue;
// 非法
pint = &newValue;
// 非法
*pint = 6;

指针int *前有const修饰符,指针指向地址为const修饰的int类型,“指针常量”本身不可修改,指向的const修饰的int类型变量也不可修改。

(二)常量指针

常量指针const int *指针本身是变量,指向的地址是常量。

const int myValue = 10;
const int newValue = 20;
// 指向“常量”的常量指针
const int * pint = &myValue;
// 或者
int const * pint = &myValue;
// 合法
pint = &newValue;
// 非法
*pint = 6;

因为定义指针是const修饰的指向类型,表示指向的地址不可更改。pint指针名前没有const修饰说明指针本身是变量,可以重新赋值。

五、多级指针

CC++可以使用多级指针指向同一块内存空间地址,也就是多层指针最终指向一个内存地址,修改任何多级指针的任何一级指针都可以修改指向地址的值。

#include <stdio.h>
int main() {int myValue;// 一级指针pintint *pint0 = &myValue;*pint0 = 5;printf("Value:%d\n", myValue);// 二级指针newPintint **pint1 = &pint0;**pint1 = 6; // 赋值myValue为6printf("Value:%d\n", myValue);// 三级指针newPintint ***pint2 = &pint1;***pint2 = 7; // 赋值myValue为6printf("Value:%d\n", myValue);return 0;
}

输出

Value:5
Value:6
Value:7

六、指针调用

C/C++函数是可以将指针作为参数定义的,在函数中定义的是形式参数,当调用该函数时将变量的地址传递给指针,函数中就可以使用指针去修改实际参数。这种调用称为指针调用。

指针调用相当于在调用函数时,将实际参数的内存地址传递给函数的形式参数,这样函数中就可以通过指针修改实际参数的值。

#include <iostream>
using namespace std;int func(int* a)
{return ++*a;
}int main()
{int i = 1;cout << "Value:" << func(&i) << endl;cout << "Value:" << i << endl;return 0; 
}

输出

Value:2
Value:2

函数中修改的指针,其实就是main()函数的i变量。

结构体作函数参数

结构体可以跟普通变量一样通过参数传递给函数,传递的可以是结构体也可以是结构体的地址,当传递结构体调用时,实际上的将实际参数拷贝给形式参数,形式参数是函数的局部变量,调用结束即销毁;传递地址调用在被调用函数中访问的实际上就是实际参数本身。

#include <stdio.h>
struct Books
{char  title[50];char  author[50];char  subject[100];int   book_id;
};/* 结构体作为参数 */
int func(struct Books book1)
{// 结构体使用(.)访问成员变量book1.book_id += 1;return book1.book_id;
}/* 结构体作为指针参数 */
int func1(struct Books* book1)
{// 指针指向的结构体,使用->访问成员变量// 修改指针指向结构体,就是结构体本身,非函数调用时创建的局部变量// book1实际上就是main()函数的bookbook1->book_id += 1;return book1->book_id;
}int main() {struct Books book;book.book_id = 5;int i;/* 传值调用 */i = func(book);printf("func, %d, %d\n", book.book_id, i);/* 传址调用 */i = func1(&book);printf("func1, %d, %d\n", book.book_id, i);return 0;
}

输出

func, 5, 6
func1, 6, 6

func1()传递结构体的指针

相关文章:

C/C++指针

指针&#xff08;pointer&#xff09;是C/C语言中的一种数据类型。指针与int、char等数据类型相似&#xff0c;都是在内存中开辟相应类型的数据区域使用&#xff0c;不同的是int存储的是整数值&#xff0c;而指针存储的是内存地址。指针是在内存中开辟指针类型的区域存储内存地…...

2024 基于 Rust 的 linter 工具速度很快

2024 年 Web 工具的一大趋势是使用 Rust 重写现有工具。Rust 是一种出色的编程语言&#xff0c;能生成运行速度惊人的二进制文件&#xff0c;且与其它 Web 工具的互操作性极佳&#xff0c;这得益于 WebAssembly 的帮助。swc 和 Turbopack 等工具的速度提升为快速开发体验带来了…...

JWT相关问题及答案(2024)

1、什么是 JWT&#xff0c;它通常用于什么目的&#xff1f; JWT&#xff08;JSON Web Token&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在不同实体之间安全地传输信息。它由三个部分组成&#xff1a;头部&#xff08;Header&#xff09;、载…...

Linux例行性工作 at和crontab命令

1&#xff0c;例行性工作 例行性工作 —— 在某一时刻&#xff0c;必须要做的事情 —— 定时任务 &#xff08;比如&#xff1a;闹钟&#xff09; 例行性工作分为两种&#xff1a;“单一的例行性工作 at”和“循环的例行性工作 crontab” 2&#xff0c;单一执行的例行性工作 …...

cookie共享和session共享实例演示

1、cookie共享实例 1.test1.share.com/index.php setcookie(dangqian, value, [domain > test1.share.com]); setcookie(gen, value, [domain > share.com]);2、test2.share.com/index.php $cookies $_COOKIE; // 打印所有Cookie的名称和值 foreach ($cookies as $n…...

设计模式之开闭原则:如何优雅地扩展软件系统

在现代软件开发中&#xff0c;设计模式是解决常见问题的最佳实践。其中&#xff0c;开闭原则作为面向对象设计的六大基本原则之一&#xff0c;为软件系统的可维护性和扩展性提供了强大的支持。本文将深入探讨开闭原则的核心理念&#xff0c;以及如何在实际项目中运用这一原则&a…...

Python Pandera 用于数据验证和清洗:是一个强大的工具用起来

今天为大家分享一个非常好用的 Python 库 - pandera。 Github地址&#xff1a;https://github.com/unionai-oss/pandera 在数据科学和数据分析中&#xff0c;数据的质量至关重要。不良的数据质量可能导致不准确的分析和决策。为了确保数据的质量&#xff0c;Python Pandera 库…...

英诺赛科推出BMS方案,搭载100V双向导通VGaN

BMS 俗称电池保姆或电池管家&#xff0c;主要是为了智能化管理及维护各个电池单元&#xff0c;防止电池出现过充电和过放电&#xff0c;保障电池安全使用的同时延长使用寿命。 当前市面上出现的电池管理系统大多数采用 Si MOS&#xff0c;由于 Si MOSFET 具有寄生二极管&#x…...

如何用Mac工具制作“苹果高管形象照”

大伙儿最近有没有刷到“苹果高管形象照”风格&#xff0c;详细说来就是&#xff1a; 以苹果官网管理层简介页面中&#xff0c;各位高管形象照为模型&#xff0c;佐以磨皮、美白、高光等修图术&#xff0c;打造的看上去既有事业又有时间有氧的证件照&#xff0c;又称“苹…...

回环检测算法:Stable Trangle Descriptor

回环检测是指检测传感器的两次测量&#xff08;如图像、激光雷达扫描&#xff09;是否发生在同一场景&#xff0c;它是对于SLAM问题至关重要。基于激光雷达的回环检测应该满足如下要求&#xff1a; 无论视点如何变化&#xff0c;回环检测方法应该实现旋转和平移不变性&#xf…...

MetaGPT入门(二)

接着MetaGPT入门&#xff08;一&#xff09;&#xff0c;在文件里再添加一个role类 class SimpleCoder(Role):def __init__(self,name:str"Alice",profile:str"SimpleCoder",**kwargs):super().__init__(name,profile,**kwargs)self._init_actions([Write…...

AI嵌入式K210项目(4)-FPIOA

文章目录 前言一、FPIOA是什么&#xff1f;二、FPIOA代码分析总结 前言 磨刀不误砍柴工&#xff0c;在正式开始学习之前&#xff0c;我们先来了解下K210自带的FPIOA&#xff0c;这个概念可能与我们之前学习STM32有很多不同&#xff0c;STM32每个引脚都有特定的功能&#xff0c…...

FPGA开发设计

一、概述 FPGA是可编程逻辑器件的一种&#xff0c;本质上是一种高密度可编程逻辑器件。 FPGA的灵活性高、开发周期短、并行性高、具备可重构特性&#xff0c;是一种广泛应用的半定制电路。 FPGA的原理 采用基于SRAM工艺的查位表结构&#xff08;LUT&#xff09;&#xff0c;…...

上海亚商投顾:沪指冲高回落 旅游板块全天强势

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日冲高回落&#xff0c;创业板指跌近1%&#xff0c;北证50指数跌超3%。旅游、零售板块全天强势&#xf…...

Linux网络--- SSH服务

一、ssh服务简介 1、什么是ssh SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程复制等功能。SSH 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令&#xff0c;SSH 为建立在…...

2.1 数组

2.1 数组 &#xff08;1) 概述 定义 在计算机科学中&#xff0c;数组是由一组元素&#xff08;值或变量&#xff09;组成的数据结构&#xff0c;每个元素有至少一个索引或键来标识 因为数组内的元素是连续存储的&#xff0c;所以数组中元素的地址&#xff0c;可以通过其索引…...

超维空间M1无人机使用说明书——53、ROS无人机二维码识别与降落——V2升级版本

引言&#xff1a;使用二维码引导无人机实现精准降落&#xff0c;首先需要实现对二维码的识别和定位&#xff0c;可以参考博客的二维码识别和定位内容。本小节主要是通过获取拿到的二维码位置&#xff0c;控制无人机全向的移动和降落&#xff0c;本小节再V1版本的基础上增加了动…...

瑞萨IDE:CS+ for CC进行BootLoader升级时开发环境配置

瑞萨IDE:CS+ for CC进行BootLoader升级时开发环境配置 2023-06-17 726 发布于河北 版权 简介: BootLoader程序设计是常用的嵌入式升级方案之一,通过使用UART、SPI、IIC等接口实现对嵌入式节点的远程升级。本片博文并不是讲解如何实现BootLoader升级程序,而是讲解使用CS+…...

翻译: Streamlit从入门到精通 显示图表Graphs 地图Map 主题Themes 二

Streamlit从入门到精通 系列&#xff1a; 翻译: Streamlit从入门到精通 基础控件 一 1. 使用Streamlit显示图表Graphs 1.1 为什么我们需要可视化&#xff1f; 数据可视化通过将数据整理成更容易理解的格式来讲述故事&#xff0c;凸显趋势和异常点。好的可视化能够讲述一个故…...

Java 开源扫雷游戏 JMine 发布新版 3.0 及介绍视频

Java 开源扫雷游戏 JMine 发布新版 3.0 及介绍视频 Java 开源扫雷游戏 JMine 是笔者开发的基于 Swing 的 Java 扫雷游戏&#xff0c;现已发布新版 3.0 及其介绍视频。视频请见&#xff1a; https://www.bilibili.com/video/BV1RK4y1z7Qz/ 老版本 JMine 1.2.5 的介绍视频请见…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...