指针进阶详解

news2024/9/23 20:23:14

目录

指针基本概念

1.字符指针

2.指针数组

3.数组指针

对数组名的理解

小结


指针基本概念

在初阶指针中我们了解到一些指针的基本概念:
1.指针就是个变量,用来存放地址,地址唯一标识一块内存

2.指针的大小是固定的4/8个字节(32位/64位平台)

3指针是有类型的,指针的类型决定了指针的+整数的步长,指针解引用时操作的权限

例如,char*类型的指针解引用,它的权限(或步长)在32位平台下只有一个字节,而int*型的指针在32位平台下的权限(步长)为4个字节。

1.字符指针

#include<stdio.h>
int main()
{
	char ch = 'w';
	char* pc = &ch;
	*pc = 'w';//这里的pc就是一个字符指针
	return 0;
}

 这里的pc就是一个字符指针,可以通过解引用pc来对w进行操作。

#include<stdio.h>
int main()
{
char arr[]="abcdef";//数组内容为字符串
//char *p="abcdef";//指针存储的内容为字符串"abcdef"的首个字母的地址
const char *p="abcdef";//abcdef为常量字符串,需要加const来修饰
return 0;
}

 这两个定义有什么区别, char arr[]='' abcdef''只是一个对数组普通的初始化,将字符串''abcdef''放数组arr中

char *p="abcdef"中,abcdef是常量字符串,其前面需要用const来修饰,那么第二个操作是不是直接将整个字符串保存在字符指针中了呢答案是否定的。

该操作实际上是将常量字符串''abcdef''的首个字符的地址保存到字符指针*p中

而我们应该如何验证呢?

#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	const char* p = "abcdef";
	printf("%s\n",p);
	printf("%c",*p);
	return 0;
}

 若此时p中存储的是字符串"abcdef"首字符的地址,那么第一个printf打印的结果应为"abcdef"

第二个printf中对字符指针p进行*解引用的结果应该是字符串首字符a。

 于是我们得到了结论:该操作实际上是将常量字符串''abcdef''的首字符的地址保存到字符指针*p中

 有这样一道面试题来练手,如下:

#include <stdio.h>
int main()
{
  char str1[] = "hello bit.";
  char str2[] = "hello bit.";
  const char *str3 = "hello bit.";
  const char *str4 = "hello bit.";
  if(str1 == str2)
    printf("str1 and str2 are same\n");
  else
    printf("str1 and str2 are not same\n");

  if(str3 == str4)
    printf("str3 and str4 are same\n");
  else
    printf("str3 and str4 are not same\n");

  return 0; 
}

 

可以看到str1与str2是不相同的,而str3与str4是相同的,那么这究竟是什么原因呢?

 char str1[] = "hello bit.";
 char str2[] = "hello bit.";

两个数组的内容是相同的,但是开辟的并不是同一块空间 ,str1和str2都是数组名,代表了数组首元素的地址,而两个数分别开辟了不同的内存空间,所以首元素的地址不同,所以str1与str2不同而对于str3和str4,"hello bit."由const修饰,为常量字符串同时str3与str4都是字符指针,存储的是字符指针"hello bit."的首字符的地址,且其是由const修饰的常量字符串,故str3与str4指向的空间的地址相同,所以str3==str4;

2.指针数组

类比:

整型数组-存放整型的数组;

字符数组-存放字符的数组;

指针数组-存放指针的数组;

#include<stdio.h>
int main()
{
int* arr1[10];//整形指针的数组
char *arr2[4];//一级字符指针的数组
char **arr3[5];//二级字符指针的数组
return 0;
}

使用指针数组模拟实现二维数组

#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int* arr[3] = {arr1,arr2,arr3};
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

用i遍历左边的数组,用j遍历右边的数组 ,结果如下图:

需要特别注意的是,指针数组模拟实现的二维数组与真正的二维数组不同的是,该指针数组中各元素地址的存放不一定是连续的。

3.数组指针

首先来做一个区分

整形指针-指向整型变量的指针,存放整型变量的地址的指针变量;

字符指针-指向字符变量的指针,存放字符变量的地址的指针变量;

数组指针-指向数组变量的指针,存放数组变量的地址的指针变量;

int*p1[10];//指针数组(p1先与[]结合)
int(*p2)[10];//数组指针(p2先与*运算符结合)

p2是指针指向的是数组,称为数组指针变量。

对数组名的理解

数组名是数组首元素的地址,但是有两个例外,如下

1.sizeof(数组名),这里的数组名不是数组首元素的地址,数组名此时表示整个数组,sizeof(数组名)计算是整个数组的大小,单位是字节。

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

除此之外,所有地方的数组名都是数组首元素的地址。

#include<stdio.h>
int main()
{
int arr[10]={0};
printf("%p\n",arr);
printf("%p\n",&arr[0]);
printf("%p\n",&arr);
return 0;
}

 前两个输出都表示的是数组首元素的地址,而第三个应该表示的是整个数组的地址,但是我们可以观察到三者的输出结果是相同的,

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr+1);
	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0]+1);
	printf("%p\n", &arr);
	printf("%p\n", &arr+1);
	return 0;
}

观察运行结果

 前两个输出+1,都只跳过了4个字节,而第三个+1跳过了40个字节,正好是数组十个元素所占的字节数,由此可见    &数组名    代表的是整个数组的地址。

#include<stdio.h>
int main()
{
int(*p)[10]=&arr;
return 0;
}

int(*p)[10]=&arr; 定义了一个数组指针,p的类型是int (*)[10]

小结

还没写完.....

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

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

相关文章

详解c++---哈希封装

目录标题 哈希桶的代码哈希桶的修改迭代器的实现const迭代器 哈希桶的代码 通过前面的学习大家应该能够很容易的写出下面的代码&#xff1a; #pragma once #include<iostream> #include<vector> using namespace std; template<class K,class V> struct Ha…

2023年互联网行业研究报告

第一章 行业概况 互联网行业是一个广泛的领域&#xff0c;包括所有利用互联网技术进行商业活动的企业和组织。这个行业的核心是互联网&#xff0c;一个全球性的网络&#xff0c;连接着数以亿计的计算设备和用户&#xff0c;使他们可以共享信息、资源和服务。 互联网行业包括网…

apache 安装配置 基础篇(-)

download 地址 apache下载 ApacheHaus是免安装的&#xff0c; 然后解压上面的文件&#xff0c;把里面 因apache 默认端口是80&#xff0c;如果这个端口被占用&#xff0c;apache服务是启动不起来的 netstat -ano|findstr 80 apache 修改端口号 创建apache服务 在apa…

ESP32-H2 固件烧录需满足的硬件环境整理

ESP32-H2 默认通过 UART0 &#xff08;即 TXD&#xff08;GPIO24&#xff09;和 RXD&#xff08;GPIO23&#xff09;&#xff09;下载固件。 Windows 下可使用 Flash download tool 工具来下载编译后的 bin 文件&#xff1b; 运行 flash_download_tool.exe 的文件 选择开发…

SkyEye处理器仿真系列:龙芯2K1000处理器

​SkyEye简介&#xff1a; 天目全数字实时仿真软件SkyEye作为基于可视化建模的硬件行为级仿真平台&#xff0c;能够为嵌入式软件提供虚拟化运行环境&#xff0c;开发、测试人员可在该虚拟运行环境上进行软件开发、软件测试和软件验证活动。小到芯片&#xff0c;大到系统&#…

win10 DBeaver (升级)下载、安装、彻底卸载

DBeaver &#xff08;升级&#xff09;下载及安装 一、DBeaver 下载二、安装三、DBeaver 的基本使用 - mysql连接四、DBeaver 彻底卸载 DBeaver是一种通用数据库管理工具&#xff0c;适用于需要以专业方式使用数据的每个人&#xff1b;适用于开发人员&#xff0c;数据库管理员&…

苹果笔买原装的还是随便买?便宜好用的手写笔推荐

自从ipad和其他的平板电脑都搭配上了电容笔以后&#xff0c;电容笔很好地取代了我们的手指&#xff0c;书写的效率就大大提升了&#xff0c;但由于苹果原装电容笔的价格不够人性化&#xff0c;一直高居不下给普通人带来了很大的负担&#xff0c;特别是对于学生们来说&#xff0…

QT DAY1

做一个窗口界面 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);//设置窗口标题、图标this->setWindowTitle("Fly_Chat")…

6、Flume安装部署

按照采集通道规划&#xff0c;需在hadoop102&#xff0c;hadoop103&#xff0c;hadoop104三台节点分别部署一个Flume。可参照以下步骤先在hadoop102安装&#xff0c;然后再进行分发。 1、Flume入门 1.1、 Flume安装部署 1.1.1、 安装地址 &#xff08;1&#xff09; Flume官…

全网最牛,Web自动化测试Selenium八大元素定位实战(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 安装Selenium和下…

BFT 最前线|OpenAI暂时下线ChatGPT”浏览“功能;Stability AI CEO:5年内,人类程序员将不复存在

原创 | 文 BFT机器人 AI视界 TECHNOLOGY NEWS 01 Open AI暂时下线ChatGPT“浏览”功能 日前OpenAI方面宣布&#xff0c;面向ChatGPT Plus用户的"浏览"功能会在某些情况下出现故障&#xff0c;因此已于7月3日暂时禁用了这一功能。该功能是为了提高ChatGPT的搜索体验…

威胁检测和取证日志分析

在网络中&#xff0c;威胁是指可能影响其平稳运行的恶意元素。因此&#xff0c;对于任何希望搁置任何财政损失或生产力下降机会的组织来说&#xff0c;威胁检测都是必要的。为了先发制人地阻止来自各种来源的任何此类攻击&#xff0c;需要有效的威胁检测情报。 威胁检测可以是…

mmap函数

参考 https://blog.csdn.net/bhniunan/article/details/104105153void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);参数 addr&#xff1a;出参&#xff0c; 指定映射的起始地址&#xff0c;通常设为NULL&#xff0c;由内核来分配 len&#x…

网络编程3——TCP Socket实现的客户端服务器通信完整代码(详细注释帮你快速理解)

文章目录 前言一、理论准备Socket套接字是什么TCP协议的特点 二、TCP 流套接字提供的APIServerSocket APISocket API 三、代码实现请求响应式 客户端服务器服务器客户端疑惑解答为什么服务器进程需要手动指定端口号而客户端进程不需要为什么客户端中的服务器IP与端口号是"…

Mysql架构篇--Mysql 主从同步方案

文章目录 前言一、传统的主从复制&#xff1a;1 原理&#xff1a;2 缺点&#xff1a; 二、半同步复制&#xff08;Semi-Synchronous Replication&#xff09;&#xff1a;三、组复制&#xff1a;1 原理&#xff1a;2 实现&#xff1a;2.1 myql 实例安装&#xff1a;2.1 myql 实…

量子近似优化算法(QAOA)入门(1):从量子绝热算法(QAA)角度的直观理解

文章目录 前言&#xff1a;量子计算的本质是测量一、基于量子逻辑电路的常用算法1.NISQ&#xff1a;Noisy Intermediate-Scale Quantum&#xff08;含噪声中等规模量子&#xff09; 二、量子绝热算法&#xff08;QAA&#xff1a;Quantum Adiabatic Algorithm&#xff09;1.QAA的…

【KingFusion】用KingFusion3.6创建一个客户端工程的步骤

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 今天学习用KingFusion3.6创建一个客户端工程&#xff0c;以下记录创建过程。 客户端组件作为KingFusion3.6的数据展示功能模块&#xff0c;其主要功能是通过组态组态式配置以及丰富的图表元素、动画连接等多样的展示形…

ROS:TF坐标变换

目录 一、TF坐标变换背景二、概念三、静态坐标变换3.1概念3.2实际用例3.2.1分析3.2.2流程3.2.3C实现 一、TF坐标变换背景 机器人系统上&#xff0c;有多个传感器&#xff0c;如激光雷达、摄像头等&#xff0c;有的传感器是可以感知机器人周边的物体方位(或者称之为:坐标&#…

《LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS》论文笔记

引言 全量参数微调在LLM背景下由“不方便”演变为“不可行|高昂成本”&#xff0c;基于“收敛的模型参数可以压缩到低维空间”的假设&#xff1a; the learned over-parametrized models in fact reside on a low intrinsic dimension. 作者提出LORA&#xff08;Low Rank Adap…

远程关闭或重新启动计算机

远程关机只是从远程位置关闭计算机的过程。主要领域是组织在没有知识的情况下失去收入将是电力费用。员工倾向于在周末打开他们的系统。不必要的电力消耗也会影响我们的环境。在这种情况下&#xff0c;系统管理员可以在周末和非工作时间安排自动系统关闭&#xff0c;或者在必要…