探索指针的奇妙世界,程序中的魔法箭头(上)

news2024/11/24 6:17:36

目录

  • 一.指针是什么
  • 二.指针和指针类型
    • 1.指针加减整数
    • 2.指针的解引用
  • 三.野指针
    • 1.野指针形成的原因
      • (1)指针未初始化
      • 指针越界访问
    • 2.如何规避野指针
      • (1)指针初始化
      • (2)小心指针越界
      • (3)指针指向的空间释放,及时置NULL
      • (4)避免返回局部变量的地址
      • (5)指针使用之前检查有效性
  • 四.指针运算
    • 1.指针加减整数
    • 2.指针减指针
    • 3.指针的关系运算
  • 五.指针和数组
  • 六.二级指针
  • 七.指针数组

一.指针是什么

指针是内存中最小单元(字节)的编号,也就是地址
我们平时口中所说的指针,通常说的是指针变量。
总结:指针就是地址,平时口头说的指针是指针变量

指针变量:我们通过取地址操作符取出变量的内存起始地址,把地址存放到一个变量中,这个变量就是指针变量。

#include<stdio.h>

int main()
{
	int a = 1;
	int* pa = &a; //pa是专门用来存放地址(指针)的,pa被称为指针变量。
	return 0;
}

总结:
指针变量就是用来存放地址的变量。(存放在指针中的值都被当成地址处理)
一个内存单元有唯一的地址。
地址的大小在32位平台上是4个字节,在64位平台上是8个字节

二.指针和指针类型

变量有不同的类型,比如整型,浮点型等等。指针也有这样的类型。

1.指针加减整数

#include<stdio.h>

int main()
{
	int a = 0x11223344;
	int* pa = &a;
	printf("%p\n", pa);
	printf("%p\n", pa + 1);

	return 0;
}

在这里插入图片描述

所以指针的类型决定了指针向前或向后走一步有多大距离

#include<stdio.h>

int main()
{
	char a = 0x11223344;
	char* pa = &a;
	printf("%p\n", pa);
	printf("%p\n", pa + 1);

	return 0;
}

在这里插入图片描述

2.指针的解引用

#include<stdio.h>

int main()
{
	printf("%d\n", sizeof(char*));
	printf("%d\n", sizeof(short*));
	printf("%d\n", sizeof(int*));
	printf("%d\n", sizeof(long*));
	printf("%d\n", sizeof(float*));
	printf("%d\n", sizeof(double*));

	return 0;
}

在这里插入图片描述

我们通过计算不同类型指针变量的大小,发现在64位平台上均是8个字节。
那么指针类型的意义是什么呢?

在这里插入图片描述
在这里插入图片描述
如果改为char类型,44 33 22 11不会变成00 00 00 00,而是会变成 00 33 22 11

总结:
int*的指针解引用可以访问4个字节
char*的指针解引用可以访问1个字节
所以指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)

三.野指针

指向的位置不可知(随机,不正确,没有明确限制)的指针被称为野指针。

1.野指针形成的原因

(1)指针未初始化

#include<stdio.h>

int main()
{
	int* p; //局部变量指针未初始化,默认为随机值
	*p = 10; 
	return 0;
}

指针越界访问

#include<stdio.h>

int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i <= 11; i++)
	{
		//当指针指向的范围超出数组的范围时,指针就是野指针。
		*(p++) = i;
	}
	return 0;
}

2.如何规避野指针

(1)指针初始化

1.明确知道指针初始化为谁的地址,就直接初始化
2.不知道指针初始化为什么值,暂时初始化为NULL

//指针初始化
#include<stdio.h>
int main()
{
	int a = 10;
	int* p1 = &a;
	int* p2 = NULL;
	return 0;
}

(2)小心指针越界

(3)指针指向的空间释放,及时置NULL

当释放空间后赶紧置空,避免成为野指针。大街上一条狗脱离主人,要把它栓到一棵树上,避免成为野狗。

(4)避免返回局部变量的地址

(5)指针使用之前检查有效性

if (p != NULL)
{
	//使用
}

四.指针运算

1.指针加减整数

#include<stdio.h>

int main()
{
	int arr[10] = { 0 };
	int* p = &arr[0];
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		*p = i;
		p++;
	}
	p = arr;
	for (i = 0; i < sz; i++)
	{
		printf("%d\n", *(p + i));
	}
	//for (i = 0; i < sz; i++)
	//{
	//	printf("%d\n", arr[i]);
	//}
	return 0;
}

2.指针减指针

我们知道指针实际上就是地址,指针减指针也就是地址减去地址

>#include<stdio.h>

int main()
{
	int arr[10] = { 0 };
	printf("%d\n", &arr[9] - &arr[0]);
	printf("%d\n", &arr[0] - &arr[9]);
	return 0;
}

在这里插入图片描述

结论:指针减去指针得到的数值的绝对值是两个指针之间的元素个数
指针和指针相减的前提是两个指针指向同一块空间

//计算字符串长度
#include<stdio.h>

//int length(char* p) 
//{
//	int count = 0;
//	while (*p != '\0')
//	{
//		count++;
//		p++;
//	}
//	return count;
//}

//int length(char* p)
//{
//	if (*p == '\0')
//		return 0;
//	else
//		return 1 + length(p + 1);
//}

int length(char* p)
{
	char* start = p;
	while (*p != '\0')
	{
		p++;
	}
	return p - start;
}

int main()
{
	char arr[] = "abcdef";
	int len = length(arr);
	printf("%d\n", len);
	return 0;
}

3.指针的关系运算

指针的关系运算就是指针与指针之间比大小。

看这样一段代码

#define N 5
float v[N];
float* vp;
for (vp = &v[N]; vp > &v[0]; )
{
	*--vp = 0;
}

在这里插入图片描述

将上述代码稍作修改

#define N 5
float v[N];
float* vp;
for (vp = &v[N]; vp >= &v[0]; vp--) //这里变成了大于等于
{
	*vp = 0;
}

在这里插入图片描述

这段代码没什么问题也更容易理解。但是标准规定允许指向数组元素的指针与指向数组最后一个元素后面位置的指针比较,但是不允许与指向第一个元素前面位置的指针比较
在这里插入图片描述

五.指针和数组

我们通常所说的指针是指针变量,不是数组,是专门用来存放地址的。
数组是一块连续的空间,用来存放相同类型的数据。
联系:数组名是数组首元素的地址,地址就是指针。当我们知道数组首元素的地址,又因为数组是连续存放的,所以可以通过指针访问数组

//通过指针访问数组
#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d\t%d\n", *(p + i), arr[i]);
	}
	return 0;
}

在这里插入图片描述

我们可以看到 *(p + i)与arr[i]是等价的

六.二级指针

#include<stdio.h>
int main()
{
	int a = 10;
	int* p = &a;

	return 0;
}

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

#include<stdio.h>
int main()
{
	int a = 10;
	int* p = &a;
	int** pp = &p;//pp就是二级指针变量
	return 0;
}

在这里插入图片描述
二级指针变量就是用来存放一级指针变量的地址
一级指针变量用来存放变量的地址,这里就是a的地址

在这里插入图片描述

七.指针数组

指针数组就是存放指针的数组,也就是说指针数组是数组,并不是指针。

#include<stdio.h>
int main()
{
	char arr1[] = "ni hao";
	char arr2[] = "hello";
	char arr3[] = "happy";

	char* parr[] = {arr1,arr2,arr3};//指针数组
	return 0;
}

在这里插入图片描述

打印这三个字符串

	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s\n", parr[i]);
	}

在这里插入图片描述

数组parr里面有3个元素,分别是数组arr1,arr2,arr3
通过指针数组,将这3个数组联系起来了

#include<stdio.h>

int main()
{
	int arr1[] = { 11,12,13,14,15 };
	int arr2[] = { 21,22,23,24,25 };
	int arr3[] = { 31,32,33,34,35 };

	int* parr[] = { 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;
}

这里类似于二维数组,并不是真正的二维数组。真正的二维数组的存储在内存中是连续的。

上述代码的结果:
在这里插入图片描述

这很像是二维数组打印出来的结果,区别:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

SpringSecurity+JWT前后端分离架构登录认证

目录 1. 数据库设计 2. 代码设计 登录认证过滤器 认证成功处理器AuthenticationSuccessHandler 认证失败处理器AuthenticationFailureHandler AuthenticationEntryPoint配置 AccessDeniedHandler配置 UserDetailsService配置 Token校验过滤器 登录认证过滤器接口配置…

理解PCIE设备透传

PCIE设备透传解决的是使虚拟机直接访问PCIE设备的技术&#xff0c;通常情况下&#xff0c;为了使虚拟机能够访问Hypervisor上的资源&#xff0c;QEMU&#xff0c;KVMTOOL等虚拟机工具提供了"trap and emulate"&#xff0c; Virtio半虚拟化等机制实现。但是这些实现都…

用通俗易懂的方式讲解:使用 Langchain 和 Hugging Face ,轻松实现大模型 RAG 用法

检索增强生成&#xff08;RAG&#xff09;是一种与预训练的大型语言模型&#xff08;LLM&#xff09;和自己的数据一起工作的模式&#xff0c;用于生成响应。 现在我将向大家介绍在代码中实现 RAG 的过程。让我们开始使用 Langchain 和 Hugging Face 实现 RAG&#xff01; 文章…

matlab appdesigner系列-常用14-树(复选框)

之前系列常用9&#xff0c;为单个复选框。树&#xff0c;就是多个复选框形成的选项组 示例&#xff1a;列举湖北省的几个城市 湖北省 武汉 宜昌 襄阳 荆州 1&#xff09;将树&#xff08;复选框&#xff09;拖拽到画布上&#xff0c;方式1就是&#xff1a;文字可以在右侧…

【线上问题】CompletableFuture与线程池使用不当导致服务整个挂掉

Informal Essay By English It is always a pleasure to learn 背景 在某一个风和日丽的早上&#xff0c;小组同事说昨晚线上服务有20分钟左右的不可用&#xff0c;当时内心一紧&#xff0c;不会是我写的代码有bug导致的吧&#x1f440;&#xff0c;我正了正心态&#xff0c…

[小程序]样式与配置

一、外部样式导入 使用import加外部样式表的相对路径并以 ; 表示语句结束。 import "common.wxss"; 二、全局样式和局部样式 全局样式位于app.wxss中&#xff0c;会作用于整个项目中所有页面中。 局部样式位于对应的wxss文件中&#xff0c;仅作用于当前页面&#x…

WebDriverWait太强大

selenium webdriver及wait 1 implicitly包打天下2 Linkedin无法登录返回值很乱&#xff0c;怎么破&#xff1f; 1 implicitly包打天下 有了implicitly之后&#xff0c;基本上不再关注网速之类的影响。 self.driver.implicitly_wait(511)2 Linkedin无法登录返回值很乱&#xf…

Vulnhub-TECH_SUPP0RT: 1渗透

文章目录 一、前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、使用smb服务获取信息三、密码破解四、获取webshell五、反弹shell六、web配置文件获取信息七、提权 一、前言 由于在做靶机的时候&#xff0c;涉及到的渗透思路是非常的广泛&#xff0c;所以在写…

ad18报错:clearance constraint

最常见的报错&#xff0c;直译过来的意思&#xff1a;间隙约束。也就是约束PCB中的电气间距&#xff0c;比如阻容各类元件的焊盘间距小于规则中的设定值&#xff0c;即报警。 Altium Designer 中的 Clearance Constraint 错误如何修改-CSDN博客 【Altium Designer21】DRC规则…

Vulnhub靶机:FunBox 2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;FunBox 2&#xff08;10.0.2.27&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.com/funbo…

决策树的分类

概念 决策树是一种树形结构 树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果 决策树的建立过程 1.特征选择&#xff1a;选取有较强分类能力的特征。 2.决策树生成&#xff1a;根据选择的特征生…

【代码随想录07】344.反转字符串 541. 反转字符串II 05.替换空格 151.翻转字符串里的单词 55. 右旋转字符串

目录 344. 反转字符串题目描述做题思路参考代码 541. 反转字符串 II题目描述参考代码 05. 替换数字题目描述参考代码 151. 反转字符串中的单词题目描述参考代码 55. 右旋转字符串题目描述参考代码 344. 反转字符串 题目描述 编写一个函数&#xff0c;其作用是将输入的字符串反…

HTML以及CSS相关知识总结(一)

近日就开始回顾html和css相关知识啦&#xff0c;并且会学习html5和css3的新知识&#xff0c;以下是我对记忆不太深刻的地方以及新知识点的总结&#xff1a; Web标准&#xff1a; 结构&#xff1a;用于对网页元素进行整理和分类&#xff0c;即HTML 表现&#xff1a;用于设置网页…

CentOS Linux操作系统源码安装最新Redis版本,使用JSON数据类型踩入新坑

最近有空查阅了redis官网&#xff0c;发现redis数据类型不止Strings、Lists、Sets、Hashes、Sorted sets&#xff0c;还多了几种&#xff0c;决定先试用下JSON数据类型 1、安装Redis软件 JSON数据类型&#xff0c;对Redis版本有要求&#xff0c;需要大于4.0版本。下图是华为云…

Transformer|1.4 CNN遇到的问题与窘境

文章目录 CNN遇到的问题与窘境transformer 的优势 CNN遇到的问题与窘境 判断一个人是否为美人&#xff0c;既要看她各个五官&#xff0c;也要看她各个五官占的比例和协调。 既要照顾好局部信息&#xff0c;也要照顾好全局信息。 局部信息用小的感受野进行感受&#xff0c;而全局…

【操作系统和计网从入门到深入】(六)进程间通信

前言 这个专栏其实是博主在复习操作系统和计算机网络时候的笔记&#xff0c;所以如果是博主比较熟悉的知识点&#xff0c;博主可能就直接跳过了&#xff0c;但是所有重要的知识点&#xff0c;在这个专栏里面都会提到&#xff01;而且我也一定会保证这个专栏知识点的完整性&…

python算法与数据结构---单调栈与实践

单调栈 单调栈是一个栈&#xff0c;里面的元素的大小按照它们所在栈的位置&#xff0c;满足一定的单调性&#xff1b; 性质&#xff1a; 单调递减栈能找到左边第一个比当前元素大的元素&#xff1b;单调递增栈能找到左边第一个比当前元素小的元素&#xff1b; 应用场景 一般用…

19.云原生CICD之ArgoCD入门

云原生专栏大纲 文章目录 ArgoCDArgoCD 简介GitOps介绍Argo CD 的工作流程argocd和jinkens对比kustomize介绍ArgoCD和kustomize关系 安装argocdargocd控制台介绍首页应用创建表单SYNC OPTIONS&#xff08;同步选项&#xff09;SYNC POLICY&#xff08;同步策略&#xff09; 应…

视频异常检测论文笔记

看几篇中文的学习一下别人的思路 基于全局-局部自注意力网络的视频异常检测方法主要贡献&#xff1a;网络结构注意力模块结构&#xff1a; 融合自注意力和自编码器的视频异常检测主要贡献&#xff1a;网络结构Transformer模块动态图 融合门控自注意力机制的生成对抗网络视频异常…

Kafka框架详解

Kafka 1、Kafka介绍 ​ Kafka是最初由linkedin公司开发的&#xff0c;使用scala语言编写&#xff0c;kafka是一个分布式&#xff0c;分区的&#xff0c;多副本的&#xff0c;多订阅者的消息队列系统。 2、Kafka相比其他消息队列的优势 ​ 常见的消息队列&#xff1a;Rabbit…