当前位置: 首页 > 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 的介绍视频请见…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...