指针数组和数组指针、字符指针

news2025/4/11 15:13:13

文章目录

    • 指针
    • 字符指针
        • 实例一
        • 实例二
    • 指针数组
        • 实例一
        • 实例二
        • 实例三
    • 数组指针
        • 实例一
        • 实例二
        • 实例三-看书呗

指针

1.指针是个变量,用来存放地址,地址将唯一标识一块内存空间
内存编号=地址=指针
2.指针的大小是固定的,32位平台是4个字节,64位平台是8个字节

字符指针

原文:
https://blog.csdn.net/m0_53558236/article/details/125949857

实例一

char* 类型的指针称为字符指针

int main()
{
    char ch = 'w';
    char *pc = &ch;//pc是指向一个字符变量
	*pc = 'w';
    return 0;
}

char* pc = &ch;//前面的表示pc是个指针变量,char表示pc指向的变量的类型是char类型
等价于:
char
pc;
pc = &ch;

实例二

int main()
{
    char* p = "hello world";
    printf("%s", p);
    return 0;
}

char* p = “hello world”;
特别容易让人以为是把字符串 hello world 放到字符指针 p 里
了,其实不是的。
"hello world"是一个常量字符串,存放在内存的常量区。
上面表达式的作用是:把常量字符串"hello world"的第一个字符h的地址赋值给p。

我们可以来测试一下是不是这样?
printf(“%c”, *p);
上面说p指向 hello world的首字母h的地址,那么对p解引用,*p就是h,我们来运行一下看是不是这样
在这里插入图片描述
可以看到,确实是这样的
其实

p指针是指向了hello world这个字符串,但它只是存了h的地址,指向了h就相当于指向了hello
world整个字符串,因为这个字符串是连续的。 所以我们要打印一个字符的时候,用printf(“%c”, p);用%c和p
如果我们要打印整个字符串,则用printf(“%s”, p);用%s和p

在这里插入图片描述

printf(“%c”, p); printf(“%s”, p);
写成%s的时候,后面“p”这里只提供一个地址就可以了。p里面存的是h的地址,打印时就从p里面存的h的地址开始打印整个字符串hello
world。 💡注意:
这里写一个p就可以了,不要写成
p了。*p指的是一个字符h。写%s表示打印字符串,后面给一个地址就可以了;而%c表示只打印一个字符。

隐含的问题
其实这个写法char* p = “hello world”;不太好,有的编译器可能会报错。
因为"hello world"是一个常量字符串,存放在内存的常量区是不允许改动的。而前面的char* p是不受限制的,一旦p指针重新改动,即后面的不允许改,但前面的有随意改动,程序就会报错
比如说我们来改一下p,运行时不会报错,不过一直也不会给出打印的结果,但调试一下就会显示错误
在这里插入图片描述
前面讲的时候,常量字符串用的是"hello world",这里我截屏上写的是"hello bit",一个意思,改动的是
p)可以看到确实不行。
我们可以用到const,用它来修饰p,即指针指向的内容就不能被修改了,一旦我们修改了p,编译器就会报错提醒,如下图
在这里插入图片描述
所以如果写常量字符串,我们要有一个指针指向的话,前面最好加一个const修饰,这样比较合理。

指针数组

参考文章:
https://blog.csdn.net/m0_53558236/article/details/127057577

整型数组:存放整形的数组

int arr[10]={1,2,3,4,5,6,7,8,9,10};

arr是一个数组,数组有10个元素,每个元素是整形。

字符数组:存放字符的数组

char ch[5]={‘a’,‘b’,‘c’,‘d’,‘e’};

ch是一个数组,数组有5个元素,每个元素是字符类型。

指针数组是一个存放指针的数组。

char* arr[5];//arr是存放字符指针的数组
int* arr2[4];//arr2是存放整形指针的数组

实例一


int a = 10;
int b = 20;
int c = 30;
int d = 40;

int* arr2[4] = {&a, &b, &c, &d};//arr2就是整型指针的数组

我们知道,这时,&a, &b, &c, &d的类型都是int*
内存布局如下:
在这里插入图片描述
接下来创建了arr2数组,数组里面有4个元素,元素类型是int*,这个数组的空间是连续的
在这里插入图片描述
int* arr2[4] = {&a, &b, &c, &d};意味着取地址a,指向的a的地址,取地址b,指向b的地址,以此类推
在这里插入图片描述
那么如果我们拿到了arr2数组,我们就能把a,b,c,d的值打印出来,具体操作如下:
当我们通过arr2[i],就能找到下标为i的元素,对arr2[i]解引用,即arr2[i],就能找到arr2[i]对应指向的内存的值。比如:arr2[1],就是&b,对arr2[1]解引用arr2[1],就能得到&b指向的内存b的值20了。
用个循环即可打印出10,20,30,40了。

int i = 0;
for (i = 0; i < 4; i++)
{
	printf("%d ", *(arr2[i]));
}

在这里插入图片描述

实例二

我们给出

int main()
{
	
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[5] = { 2,3,4,5,6 };
	int arr3[5] = { 3,4,5,6,7 };
	int* parr[3] = { arr1,arr2,arr3 };
	//由于数组名表示数组首元素地址,
	//所以需要指针数组来存放
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		int j = 0;
		for (j = 0;j < 5;j++)
		{
			printf("%d ", parr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

上面的arr1[ ],arr2[ ],arr3[ ]代表整形数组,parr[ ]代表整形指针数组
我们知道,数组名就是首元素的地址
如代码int* parr[] = { arr1, arr2, arr3 };中arr1就代表arr1[ ]数组首元素“1”的地址

上面代码对应的内存布局如下图:

在这里插入图片描述

那么我们如果得到了parr数组,那么我们就能依次的打印出12345 23456 34567 45678了

通过parr下标为0的元素,拿到arr1的起始地址;通过parr下标为1的元素,拿到arr2的起始地址,以此类推。
在这里插入图片描述
如果还是难以理解,我们也可以这样

parr为指针数组的首元素地址,parr+i,指向了数组中下标为 i 的元素,(parr+i)表示拿到了 指针数组 parr 下标为 i
的元素,假设 i =1,就意味着拿到了arr2这个元素,arr2为数组名,代表数组arr2的首元素地址。arr2+j
意味着指向了arr2数组中下标为 j 的元素,
(arr2+j)意味着拿到了下标为 j 的元素。所以
((parr+i)+j)相当于访问了arr1,arr2,arr3三个数组中的所有元素。

parr[i] == *(parr+i)
parr[i][j] == *(parr[i]+j)== *(*(parr+i)+j)==(*(parr+i))[j]

❗注意:这里看起来像是二维数组或二级指针,其实不是的,这里用的是其实是指针数组,不要混淆了。二级指针是用来存放一级指针变量的地址的,和二维数组也没有关系。

我们来看看运行结果
在这里插入图片描述

实例三

我们给出

char* arr[5] = {neijvbucun"Aaaa", "Bbbb", "Cccc", "Dddd", "Eeee"};

arr是个含有5个元素的数组,每个元素的类型是char*,我们用5个常量字符串去初始化是可以的,相当于arr中存放的依次是首字符A,B,C,D,E的地址。
因为里面放的都是常量字符串,每个元素都是不允许改的,所以我们在char*前面加上const,这样会更好一些。

const char* arr[5] = {"Aaaa", "Bbbb", "Cccc", "Dddd", "Eeee"};

内存布局如下图

在这里插入图片描述

然后我们可以打印这些字符串

int main()
{
	const char* arr[5] = { "Aaaa", "Bbbb", "Cccc", "Dddd", "Eeee" };
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%s\n", arr[i]);
	}
	printf("%s\n", arr[2]);
	return 0;
}

运行一下:

在这里插入图片描述

数组指针

此部分原文
https://blog.csdn.net/bingbing_bang/article/details/123290615
什么是数组指针?数组指针是数组吗?

数组指针并不是数组,而是一个指针,存放的是数组的地址,是能够指向数组的指针

表达形式:int (*p)[10]

p是一个指针,指向的是一个数组的地址,数组有10个元素,每个元素是int类型

注意:不要写成 int p [10] 这个表达式并不是数组指针,因为号的优先级低于[ ]

所以p先与[10]结合,构成数组,然后数组有10个元素,每个元素是int*类型,代表指针数组。

那数组指针该如何用呢?

在这里插入图片描述

将数组arr的地址取出来,放到数组指针p中。

再次重申一遍数组名和 &数组名的区别

通常情况下,数组名代表数组首元素的地址,但是有两个例外

1.sizeof(数组名),这里的数组名代表整个数组,计算的是整个数组的大小

2.&数组名,这里数组名表示的是整个数组,取出的是整个数组的地址。

在这里插入图片描述

sizeof(arr)和sizeof(arr[0]),计算的分别是数组的大小和数组首元素的大小,但是这里打印出来的数组名和&数组名怎么一样啊,不是代表的含义不同吗?

这两个地址虽然一样但是意义还确实不同,一个代表首元素的地址,一个代表整个数组的地址,数组有10个元素,也有起始位置的地址,因此显示的也是首元素的地址。但不代表&arr和arr含义一样。

举一个简单的例子进行验证,令arr+1 ,&arr+1 ,分别打印出来此时的地址,如果是首元素地址,那跳过的应该是4个字节,如果是数组的地址,那跳过的是整个数组的大小,也就是40

在这里插入图片描述

数组指针怎么用?

实例一

在这里插入图片描述

两个函数都能完成数组内容的打印,可是print2函数理解和使用起来更加复杂,并没有print1函数直观,其原理一样,但是print2函数对其进行了复杂化,先解引用找到数组名,再通过数组名找到元素地址,再对其进行解引用找到元素内容,太冗余,明明可以直接传数组名进行操作,多此一举。

确实,数组指针一般不会用到一维数组上

实例二

打印二维数组的内容

在这里插入图片描述

在这里用数组指针接收,对其进行了降维处理,将二维数组变为一维数组进行处理,更容易理解。

实例三-看书呗

在这里插入图片描述在这里插入图片描述![在这里插入图片描述](https://img-blog.csdnimg.cn/8eaf308d7fe547269eae160a44007f00.jpeg在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述

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

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

相关文章

【QT】UDP通信QUdpSocket(单播、广播、组播)

目录1. UDP通信概述2. UDP消息传送的三种模式3. QUdpSocket类的接口函数4. UDP单播和广播代码示例4.1 测试说明4.2 MainWindow.h4.3 MainWindow.cpp4.4 界面展示5. UDP组播代码示例5.1 组播的特性5.2 MainWindow.h5.3 MainWindow.cpp5.4 界面展示1. UDP通信概述 UDP是无连接、…

驱动程序开发:基于EC20 4G模块自动拨号联网的两种方式(GobiNet工具拨号和PPP工具拨号)

目录一、EC20 4G模块简介二、根据移远官方文档修改EC20 4G模组驱动  1、因为EC20 4G模组min-pice接口其实就是usb接口&#xff0c;因此需要修改Linux内核源码drivers/usb/serial/option.c文件&#xff0c;如下图&#xff1a;  2、根据USB协议的要求&#xff0c;需要在drive…

从FPGA说起的深度学习(三)

这是新的系列教程&#xff0c;在本教程中&#xff0c;我们将介绍使用 FPGA 实现深度学习的技术&#xff0c;深度学习是近年来人工智能领域的热门话题。在本教程中&#xff0c;旨在加深对深度学习和 FPGA 的理解。用 C/C 编写深度学习推理代码高级综合 (HLS) 将 C/C 代码转换为硬…

linux下安装elasticsearch步骤

linux下安装elasticsearch步骤&#xff1a; 1、Elasticsearch的下载&#xff08;选择7.8.0&#xff09; 1.1、elasticsearch国内社区&#xff1a; https://elasticsearch.cn/1.2、elasticsearch官网地址&#xff1a; https://www.elastic.co/cn/elasticsearch/1.3、elastic…

从零实现Web服务器(二): 线程池以及线程池的作用,Get和Post的区别,项目中如何编写数据库连接池,定时器优化非活跃连接

文章目录一、线程池以及线程池的作用二、手写线程池三、Get和Post的区别四、如何编写数据库连接池五、定时器优化非活跃连接5.1. 基于排序链表实现。5.2. 基于小根堆实现。5.3. 基于红黑树实现。5.4. 基于时间轮实现。5.4.1 单时间轮实现5.4.2 多时间轮实现一、线程池以及线程池…

JavaScript 入门教程||javascript 简介||JavaScript 用法

javascript 简介JavaScript 是互联网上最流行的脚本语言&#xff0c;这门语言可用于 HTML 和 web&#xff0c;更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。JavaScript 是脚本语言JavaScript 是一种轻量级的编程语言。JavaScript 是可插入 HTML 页面的编程代…

C++之lambda函数(匿名函数)

lambda函数简介lambda函数是C11标准新增的语法&#xff0c;也称为lambda表达式或匿名函数。lambda函数的特点是&#xff1a;距离近、简洁、高效和功能强大。优点声明式编程风格&#xff1a;就地匿名定义目标函数或函数对象&#xff0c;有更好的可读性和可维护性。简洁&#xff…

webspider_20230216

下载网页源代码 分析下规则 抓取咱们需要的信息 仅限于合法的行为&#xff0c;仅仅提供自动化&#xff0c;省得手工去获取图片、手机、邮箱等信息

Spring Cloud是什么?怎么理解Spring Cloud?

简介Spring Cloud项目的官方网址&#xff1a;https://projects.spring.io/spring-cloud/ Spring Cloud 并不是一个项目&#xff0c;而是一组项目的集合。在 Spring Cloud中包含了很多的子项目&#xff0c;每一个子项目都是一种微服务开发过程中遇到的问题的一种解决方案。它利…

机场航站楼告别人工巡检,提高空间安全性

机场是现代化民航基础设施体系&#xff0c;加快数字化转型、建设更高水平的智慧城市已成为城市竞争的新赛道。图扑软件基于 HT 引擎为国内民航数字化转型支撑可视化服务提供有力的一环&#xff0c;融合物联网解决方案&#xff0c;打造适配场景的智慧机场三维可视化解决方案&…

面试题整理

面试题整理 一、Java基础 1、Java 语言有哪些特点 简单易学&#xff1b; 面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b; 平台无关性&#xff08; Java 虚拟机实现平台无关性&#xff09;&#xff1b; 支持多线程&#xff08; C 语言…

#Paper Reading# Improving Language Understanding by Generative Pre-Training

论文题目: Improving Language Understanding by Generative Pre-Training 论文地址: https://www.cs.ubc.ca/~amuham01/LING530/papers/radford2018improving.pdf 论文发表于: OpenAI 2018 论文所属单位: OpenAI 论文大体内容&#xff1a; 本文主要提出了GPT&#xff08;Gene…

【SQL server】视图和索引的创建与管理

本实验数据来源课参照一下本专栏文章&#xff1a;【SQL server】进行简单查询分组、连接查询子查询和汇总&#xff08;含teaching数据库创建及实验拓展&#xff09;_Deep-sea shark的博客-CSDN博客_sql 分组汇总在SSMS中创建视图视图是一张虚表&#xff0c;数据库中只存储视图的…

关于git仓库的一些使用

配置多个ssh-key 1.生成不同的key名 如github key ssh-keygen -t rsa -C "exampleemail.com" -f ~/.ssh/github_id-rsa如gitlab key ssh-keygen -t rsa -C "examlpe企业邮箱.com" -f ~/.ssh/gitlab_id-rsa创建完成后的 macbookMacBookProdeMacBook-Pr…

STL——容器适配器、deque

一、容器适配器 1.适配器 适配器是一种设计模式&#xff08;设计模式是一套被反复使用的、多数人所知晓的、经过分类编目的、代码设计经验的总结&#xff09;&#xff0c;该种模式是将一个类的接口转换成客户希望的另外一个接口。 2.STL标准库中stack和queue的底层结构 stack…

数据结构与算法(Java版) | 就让我们来看看几个实际编程中遇到的问题吧!

上一讲&#xff0c;我给大家简单介绍了一下数据结构&#xff0c;以及数据结构与算法之间的关系&#xff0c;照理来说&#xff0c;接下来我就应该要给大家详细介绍线性结构和非线性结构了&#xff0c;但是在此之前&#xff0c;我决定还是先带着大家看几个实际编程中遇到的问题&a…

UE4 编写着色器以及各种宏的理解

参考链接&#xff1a;如何为 UE4 添加全局着色器&#xff08;Global Shaders&#xff09; - Unreal Enginehttps://docs.unrealengine.com/5.1/zh-CN/adding-global-shaders-to-unreal-engine/如何为 UE4 添加全局着色器&#xff08;Global Shaders&#xff09; - Unreal Engin…

睡眠影响寿命,这几个睡眠习惯赶紧改掉!

我们知道&#xff0c;现在睡眠不足已经成为普遍问题&#xff0c;但你知道睡眠的时长会影响寿命吗&#xff1f;熬夜对身体不好&#xff0c;已是老生常谈。但睡得过早&#xff0c;也可能影响寿命&#xff01;2021年《睡眠医学》杂志一项针对21个国家11万名参与者的研究中发现&…

重生之我是赏金猎人-SRC漏洞挖掘(十)-某大厂从废弃sso登陆口到多思路fuzz获取各地高管信息

0x01 前言 https://github.com/J0o1ey/BountyHunterInChina 欢迎亲们点个star 作者Catm78sec 前期通过灯塔 ffuf oneforall 等工具组合进行子域名收集&#xff0c;得到目标站点&#xff0c;漏洞挖掘中多次踩坑成功get腾讯某后台 0x02 渗透日常——单点登录 目标URL&…

【vcpkg】cpprestsdk之64位编译链接及踩坑

▒ 目录 ▒&#x1f6eb; 问题描述1️⃣ 多版本vs报错指定VS路径2️⃣ error LNK2001: 问题排查通过IDA打开lib文件&#xff0c;确认导出内容查看源码增加参数--editable&#xff0c;重新编译3️⃣ error LNK2001: 外部符号__imp_?close_...去除__imp_&#x1f6ec; 结论vcpkg…