c++指针【1】

news2024/11/15 14:10:13

在C++中,指针是一种特殊的变量,它存储了一个内存地址。C++指针在处理内存、数组、函数参数传递、文件I/O、动态内存分配等方面有着重要的应用。

一个指针变量通常被声明为特定类型的指针。例如,一个整数类型的指针可以指向一个整数。在声明指针变量时,应该在变量名前面加上星号(*)。

例如,下面的代码声明了一个整数类型的指针:

int* p;

 要初始化一个指针,可以使用另一个变量(或其他类型的内存地址)来赋值给它。例如:

int x = 10;  
int* p = &x;  // p现在指向x的内存地址

 在C++中,可以通过解引用操作(使用*运算符)来访问指针指向的值。例如:

std::cout << *p << endl;  // 输出10,因为p指向x的内存地址*,p就是取出这个地址的值

 获取对象地址,要想获取改地址,需要使用取地址符(操作符&);

int val = 56;
int *p = &val; //p存放变量val的地址,或者说p是指向变量val的指针
double val;
double *pd = &val; //正确:初始值是double型对象的地址
double *pd2 = pd;  //正确:初始值是指向double对象的指针

int *pi  = pd;     //错误:指针pi的类型和pd的类型不匹配
     pi  = &val;   //错误:试图把double型对象的地址赋值给int型指针

 指针值

指针的值(即地址)应属于下列4种状态之一:

1.指向一个对象。

2.指向紧邻对象所占空间的下一个位置。

3.空指针,意味着指针没有指向任何对象。

4.无效指针,也就是上述情况之外的其他值。

利用指针访问对象

如果指针指向了一个对象,则允许使用解引用符(操作符*)来访问该对象;

int val = 42;
int *p  = &val;   //p存放着变量val的地址,或者说p是指向变量val的指针
cout   <<  *p;   //由符号*得到指针p所指向的对象,输出42;

*p = 0;    //由符号*得到指针p所指向的对象,即可有p为变量val赋值
cout << *p;    //输出0 

 接引用操作,仅适用于那些确实指向了某个对象的有效指针

空指针

空指针(null pointer)不指向任何对象,在试图使用一个指针之前代码可以先检查他是否为空。以下列出几个生成空指针的方法:

int *p1 = nullptr;  //等价于int *p1 = 0;

int *p2 = 0;        //直接将p2初始化为字面常量0

//需要首先#include cstdlib

int *p3 = null;  //等价于int *p3 = 0;

得到空指针最直接的办法就是字面值nullptr来初始化指针。

赋值和指针

指针和引用都能提供对其他对象的间接访问

记住:赋值永远改变的是等号左侧的对象

void* 指针

void*是一种特殊的指针类型,可用于存放任意对象的地址。一个void*指针存放着一个地址。

double obj = 3.14,*pd = &obj; //正确:void*能存放任意类型对象的地址

void *pv = &obj; //obj可以是任意类型的对象

pv = pd;        //pv可以存放任意类型的指针

        利用 void*指针能做的事儿比较有限:拿它和别的指针比较、作为函数的输入或输出,或者赋给另外一个void*指针。不能直接操作 void*指针所指的对象,因为我们并不知道这个对象到底是什么类型,也就无法确定能在这个对象上做哪些操作。

总的概括:以void*的视角来看内存空间,没办法访问内存空间中所存的对象。

练习巩固:

 1.c++编写指针代码,分别更改指针的值以及指针所指向对象的值

#include<iostream>

int main()
{
	float  x = 3.6; //定义一个整型变量x并初始化为3.6
	float *ptr = &x ; //定义一个指向x的指针ptr

	std::cout << "原始指针的值:ptr = " << ptr << std::endl;
	std::cout << "原始指针所指向的对象的值:*ptr = " << *ptr << std::endl;

	//更改指针的值
	float  y = 2.3;
	ptr = &y;
	std::cout << "更改后指针的值:ptr = " << ptr << std::endl;
	std::cout << "更改后指针所指向对象的值: *ptr = " << *ptr << std::endl;

	//更改指针所指向对象的值
	*ptr = 3030;

	std::cout << "再次更改指针所指向的对象的值: *ptr= " << *ptr << std::endl;

 	return 0;
}

2.说明指针和引用的主要区别:

C++中的指针和引用是两个重要的概念,它们都可以用来间接访问其他对象,但它们之间存在一些关键的区别:

  1. 基本性质:指针是一个变量,存储的是另一个变量的地址;而引用是变量的别名,它和变量指向同一块内存空间。
  2. 初始化:引用在定义时必须被初始化,并且初始化后不能改变;而指针在定义时可以不被初始化,初始化后也可以改变其所指向的对象。
  3. 空值:指针可以为NULL,但引用不能。
  4. 取值方式:引用直接访问其所指向的对象,像操作普通变量一样;而指针需要通过解引用操作符*来访问其所指向的对象。
  5. 安全性:引用比指针更安全,因为引用总是指向一个存在的变量,而指针则可能指向一个不存在的内存地址。
  6. 语法形式:引用使用起来就像使用普通变量一样简单,而指针需要使用解引用操作符*来访问其所指向的对象。

总的来说,指针和引用都可以用来间接访问其他对象,但它们的使用方式和设计目标不同。指针更加灵活,可以用来操作内存中的任意地址;而引用更加安全和方便,可以像使用普通变量一样使用。

#include<iostream>

int main()
{
	int x = 10;   // 定义一个整型变量x并初始化为10  
	int* ptr = &x; // 定义一个指向x的指针ptr  
	int& ref = x;  // 定义一个引用ref,它是变量x的别名  

	// 输出指针、引用和变量的值  
	std::cout << "x = " << x << std::endl;
	std::cout << "ptr = " << ptr << ", *ptr = " << *ptr << std::endl;
	std::cout << "ref = " << ref << std::endl;

	// 修改变量的值  
	x = 20;
	ptr[0] = 30;
	ref = 40;

	// 输出指针、引用和变量的值  
	std::cout << "x = " << x << std::endl;
	std::cout << "ptr = " << ptr << ", *ptr = " << *ptr << std::endl;
	std::cout << "ref = " << ref << std::endl;

	return 0;
}

3.请简述下面这段代码的作用:

int i= 42;
int *p1 = &i;
*p1 = *p1 * *p1;

这段代码的主要作用是使用指针来修改它所指向的变量的值。

  1. int i= 42;  //定义了一个整型变量i并初始化为42。
  2. int *p1 = &i;//定义了一个整型指针p1,并将它初始化为变量i的地址。
  3. *p1 = *p1 * * p1;//这里有两个指针解引用操作(*p1),第一个解引用操作获取p1所指向的值(即变量i的值),第二个解引用操作获取p1所指向的变量的地址。然后,代码将这两个值相乘,并将结果存回p1所指向的变量中。

因此,这段代码的作用是将变量i的值从42修改为42*42(即1764)。

 4.假设p是一个int型指针,请说明下述代码的含义

if(p) // ...
if(*p) //...

这两个条件判断语句的含义是不同的。

  1. if(p) // ...这个语句是在检查指针变量 p 是否为非空(即指向一个有效的内存地址)。如果 p 非空,则会执行后面的代码块;如果 p 为空,则不会执行后面的代码块。
  2. if(*p) //...这个语句是在检查指针 p 所指向的内存地址中存储的值是否为非零。如果 *p 非零,则会执行后面的代码块;如果 *p 为零,则不会执行后面的代码块。

5.下面代码中为什么 p 合法而 lp 非法?

int i = 42;

void *p = &i;

long *lp = &i;

        在C语言中,intlong是两种不同的数据类型。int通常用于存储整数,而long通常用于存储较大的整数。在大多数平台上,intlong的长度是不同的。int通常为32位,而long通常为64位。

在这段代码中:

int i = 42;
void *p = &i;
long *lp = &i;

第一行代码定义了一个名为i的整数,并初始化为42。

第二行代码定义了一个名为pvoid指针,并将它初始化为整数i的地址。这是合法的,因为void指针是一个通用指针类型,可以存储任何数据类型的地址。

第三行代码试图定义一个名为lp的长整数指针,并将它初始化为整数i的地址。

        这是非法的,因为整数i的地址不能被直接赋给一个长整数指针。虽然它们的位数不同,但它们的对齐要求可能不同,也就是说,它们的内存模型可能不同。因此,将一个int的地址赋值给一个long指针可能会导致未定义的行为。

        在C++中,你不能将一个类型的地址直接赋给另一个类型,除非它们是兼容的类型。例如,如果你有一个指向整数的指针,你可以将它转换为指向字符的指针(因为一个字符的大小和一个整数的大小通常是一样的),但你不能将它转换为指向长整数的指针。

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

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

相关文章

【软考】13. 结构化开发方法

《系统分析与设计概述》 当前系统的物理模型 ——> 当前系统的逻辑模型 ——> 目标系统的逻辑模型 ——> 目标系统的物理模型系统开发的目的&#xff1a;当前系统的物理模型 ——> 目标系统的物理模型 系统设计基本原理 抽象、模块化&#xff08;逐步分解&#xf…

「网络编程」数据链路层协议_ 以太网协议学习

「前言」文章内容是数据链路层以太网协议的讲解。 「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、以太网协议简介二、以太网帧格式&#xff08;报头&#xff09;三、MTU对上层协议的影响四、ARP协议4.1 ARP协议的作用4.2 ARP协议报头 一、以太网协…

【Spring】IOC快速入门

文章目录 1. Spring简介2. IOC快速入门 1. Spring简介 Spring是一个开放源代码的Java SE/EE一站式轻量级开源框架&#xff0c;由Rod Johnson发起并创立。其核心是IOC&#xff08;控制反转&#xff09;和AOP&#xff08;面向切面编程&#xff09;&#xff0c;使得开发者可以将对…

『 C++类与对象』继承

文章目录 继承的概念继承方式与访问限定符基类和派生类对象赋值转换继承中的作用域隐藏 派生类的默认成员函数构造函数拷贝构造函数赋值运算符重载析构函数 继承与友元静态成员与继承关系 继承的概念 继承的机制为,允许在以该类为基础上对类进行扩展,增加功能; 通常原来也就是…

社区买菜系统 JAVA开源项目

目录 项目内容 项目获取 项目截图 项目内容 基于VueSpringBootMySQL的社区买菜系统&#xff0c;包含菜品分类模块、菜品档案模块、菜品订单模块、菜品收藏模块、收货地址模块&#xff0c;还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、…

【网安AIGC专题10.19】论文6:Java漏洞自动修复+数据集 VJBench+大语言模型、APR技术+代码转换方法+LLM和DL-APR模型的挑战与机会

How Effective Are Neural Networks for Fixing Security Vulnerabilities 写在最前面摘要贡献发现 介绍背景&#xff1a;漏洞修复需求和Java漏洞修复方向动机方法贡献 数据集先前的数据集和Java漏洞Benchmark数据集扩展要求数据处理工作最终数据集 VJBenchVJBench 与 Vul4J 的…

Unity编辑器扩展之CustomPropertyDrawer理解

一、引言&#xff0c; 在上一篇文章中提到&#xff0c;CustomEditor只能自定义单一类&#xff0c;被其他类持有的类自定义没有作用&#xff0c;这个时候就需要使用CustomPropertyDrawer属性。 二、PropertyDrawer介绍 PropertyDrawer用于自定义属性绘制器的基类。使用Proper…

【办公自动化】wps word首字下沉/文字宽度/段落底纹/图片缩放/装订线(Word的相关操作)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

『第九章』雨燕新量子引擎:结构化并发

在本篇博文中,您将学到如下内容: 1. 千呼万唤始出来:结构化并发2. async/await3. “结构化(structured)”到底是个神马?3.1 async let3.2 TaskGroup4. 非结构化并发(unstructured concurrency)4.1 非异步上下文中的 Task4.2 Detached Task4.3 延时5. 任务(Task)的取消和…

168. Excel表列名称

168. Excel表列名称 Java代码&#xff1a; 26进制&#xff0c;但是每个进制是从1开始的&#xff0c;不是从0开始&#xff1b;因此要计算要构建从0开始的求余&#xff01; class Solution {public String convertToTitle(int cn) {StringBuilder sb new StringBuilder();whi…

ElasticSearch快速入门实战

全文检索 什么是全文检索 全文检索是一种通过对文本内容进行全面索引和搜索的技术。它可以快速地在大量文本数据中查找包含特定关键词或短语的文档&#xff0c;并返回相关的搜索结果。全文检索广泛应用于各种信息管理系统和应用中&#xff0c;如搜索引擎、文档管理系统、电子…

Xtuner——报错解决汇总

文章目录 load_dataset读取jsonl文件报错 load_dataset读取jsonl文件报错 alpaca_en dict(typeprocess_hf_dataset,datasetdict(typeload_dataset, data_filesalpaca_file_path),tokenizertokenizer,max_lengthmax_length,dataset_map_fnalpaca_map_fn,template_map_fndict(t…

【C++初阶(三)】引用内联函数auto关键字

目录 前言 1. 引用 1.1 引用的概念 1.2 引用的特性 1.3 引用的权限 1.4 引用的使用 1.5 引用与指针的区别 2. 内联函数 2.1 什么是内联函数 2.2 内联函数的特性 3. auto关键字 3.1 auto简介 3.2 auto使用规则 3.3 auto不能使用的场景 4. 基于范围的for循环 4.1 范围for…

一文2000字教你从0到1实现Jmeter 分布式压测

你可以使用 JMeter 来模拟高并发秒杀场景下的压力测试。这里有一个例子&#xff0c;它模拟了同时有 5000 个用户&#xff0c;循环 10 次的情况‍。 请求默认配置 token 配置 秒杀接口 ​结果分析 ​但是&#xff0c;实际企业中&#xff0c;这种压测方式根本不满足实际需求。下面…

技术资料MF74:将图像插入单元格注释

【分享成果&#xff0c;随喜正能量】须知往生净土&#xff0c;全仗信、愿。有信、愿&#xff0c;即未得三昧、未得一心不乱&#xff0c;亦可往生。且莫只以一心不乱&#xff0c;及得念佛三昧为志事&#xff0c;不复以信、愿、净念为事。。 我给VBA的定义&#xff1a;VBA是个人…

讯飞星火大模型V3.0 WebApi使用

讯飞星火大模型V3.0 WebApi使用 文档说明&#xff1a;星火认知大模型Web文档 | 讯飞开放平台文档中心 (xfyun.cn) 实现效果 初始化 首先构建一个基础脚手架项目 npm init vuelatest用到如下依赖 "dependencies": {"crypto-js": "^4.2.0",&q…

ClickHouse快速了解

简介 ClickHouse是一个开源列式数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;用于在线分析处理&#xff08;OLAP&#xff09;&#xff1a; 列式存储&#xff1a;与传统的行式数据库不同&#xff0c;ClickHouse以列的形式存储数据&#xff0c;这使得在分析大量数据时…

嵌入式中C++ 编程习惯与编程要点分析

以良好的方式编写C class 假设现在我们要实现一个复数类complex&#xff0c;在类的实现过程中探索良好的编程习惯。 ① Header(头文件)中的防卫式声明 complex.h: # ifndef __COMPLEX__ # define __COMPLEX__ class complex {} # endif 防止头文件的内容被多次包含。 …

2.25每日一题(反常积分的计算:被积函数分母出现e的正负x次幂)

注&#xff1a;被积函数分母出现e的正负x次幂&#xff0c;这种情况需要把分母化成全部都是正次幂的情况再进行计算

【C语言】字符函数、字符串函数与内存函数

简单不先于复杂&#xff0c;而是在复杂之后。 目录 0. 前言 1. 函数介绍 1.1 strlen 1.1.1 介绍 1.1.2 strlen 函数模拟实现 1.1.2.1 计数器方法 1.1.2.2 递归方法 1.1.2.3 指针 - 指针方法 1.2 strcpy 1.2.1 介绍 1.2.2 strcpy 函数模拟实现 1.3 strcat 1…