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

这篇具有很好参考价值的文章主要介绍了探索指针的奇妙世界,程序中的魔法箭头(上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.指针是什么

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

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

#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;
}

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

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

#include<stdio.h>

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

	return 0;
}

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

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;
}

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

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

探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言
探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言
如果改为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;
}

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

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

//计算字符串长度
#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;
}

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

将上述代码稍作修改

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

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

这段代码没什么问题也更容易理解。但是标准规定允许指向数组元素的指针与指向数组最后一个元素后面位置的指针比较,但是不允许与指向第一个元素前面位置的指针比较
探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言

五.指针和数组

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

//通过指针访问数组
#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;
}

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

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

六.二级指针

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

	return 0;
}

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

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

探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言
二级指针变量就是用来存放一级指针变量的地址
一级指针变量用来存放变量的地址,这里就是a的地址

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

七.指针数组

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

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

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

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

打印这三个字符串

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

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

数组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;
}

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

上述代码的结果:
探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言

这很像是二维数组打印出来的结果,区别:
探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言
探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言
探索指针的奇妙世界,程序中的魔法箭头(上),C语言,c语言文章来源地址https://www.toymoban.com/news/detail-811876.html

到了这里,关于探索指针的奇妙世界,程序中的魔法箭头(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 解锁无限可能:深入探索Docker的奇妙世界

    Docker是一个开源的容器化平台,它以轻量级和可移植的方式打包应用程序及其所有依赖项,并提供了一种标准化的部署方式。通过使用Docker,开发人员可以将应用程序与其依赖项打包到一个称为容器的可执行单元中,然后在不同的环境中部署和运行这些容器。 容器化:Docke

    2024年02月01日
    浏览(46)
  • Python 探索 Tello 无人机的奇妙世界

    如果您希望使用 Tello 无人机拍摄照片并将其传输到您的 PC,那么您走运了! 只需几行 Python 代码,您就可以轻松控制您的 Tello 拍照,然后将 JPEG 图片传输到您的计算机。 首先,确保在 Python 环境中安装了必要的包。 你需要 djitellopy 包来与你的 Tello 通信,需要 opencv-python 包来

    2024年02月14日
    浏览(55)
  • 「探索API的奇妙世界:理解、使用和优化接口技术」

    引言: 在现代科技的时代,API(应用程序编程接口)已经成为各行业中不可或缺的关键技术。从手机应用到云计算,从社交媒体到物联网,几乎所有的软件都在背后使用着API来实现数据交互和功能扩展。在这篇文章中,我们将深入探索API的奇妙世界,从理解API的基本概念开始

    2024年02月16日
    浏览(41)
  • 探索Python条件语句的奇妙世界:解密逻辑与控制流

    Python的条件语句用来根据特定的条件决定程序的执行流程。它允许程序根据条件的真假执行不同的代码块,从而实现不同情况下的不同操作。条件语句使程序能够根据特定条件进行逻辑判断和选择性的控制,从而增强了程序的灵活性和可扩展性。那么今天将由我来带大家进入

    2024年02月12日
    浏览(75)
  • Python 集合探索:解密高效数据操作和快速算法的奇妙世界

    在 Python 的众多数据结构中,集合(Sets)是一个引人注目且实用的概念。集合提供了一种存储无顺序、唯一元素的数据结构,它们不仅可以帮助我们高效处理数据,还能应用于各种算法和问题。 本博客将带您踏上一段关于 Python 集合的探索之旅。我们将深入了解集合的基本概

    2024年02月12日
    浏览(64)
  • 惊艳的Selenium技巧:探索基础和动作链的奇妙世界

    selenium可以帮助我们便捷的获取网站中动态加载的数据,也可以便捷实现模拟登录; selenium是基于浏览器自动化的一个模块,使用可以操作浏览器来帮我们实现一些自动化的操作! Selenium 是一个广泛使用的自动化测试工具,用于测试 Web 应用程序的功能和兼容性。它提供了一

    2024年02月06日
    浏览(36)
  • 探索Python的魔法世界,开启编程奇幻之旅!

      无需魔杖,只需键盘,Python将带你进入一个充满奇幻和创造力的世界。本篇博客将引领你走进Python的魔法大门,从编程新手蜕变为编码魔法师,开启一段激动人心的编程奇幻之旅。 如果你是一名编程初学者,并且想要掌握一门强大且广泛应用的编程语言,那么Python绝对是你

    2024年02月10日
    浏览(55)
  • 编织魔法:探索Python字符串的奇幻世界

    在当今计算机编程领域中,Python语言以其简洁、优雅和易读的特性,成为了最受欢迎的编程语言之一。其中的字符串处理是Python编程中不可或缺的技术之一。本篇博客将介绍Python字符串的基本概念,包括字符串的定义、索引和切片操作。我们将深入探讨字符串的常用方法,如

    2024年02月11日
    浏览(46)
  • 【Python百宝箱】声音的数字化探索:Python引领音频奇妙世界

    在数字化时代,声音技术的迅速发展不仅革新了音乐产业,也在语音识别、虚拟现实、智能系统等领域引发了革命性变革。Python作为强大的编程语言,引领着音频处理与分析的新潮流。本文将探索Python在音频领域的广泛应用,从声音数据的处理到创意性应用。 1. librosa 介绍与

    2024年02月04日
    浏览(54)
  • Redis九种数据类型及其持久化机制:探索数据存储的奇妙世界

    目录 一、9种数据类型 3.1 Key操作 3.1.1 相关命令 练习: 3.2 String 3.2.1 结构图 3.2.2 相关命令  练习: 3.3 List(双向的链表) 3.3.1 结构图 3.3.2 相关命令 练习: 3.4 Set(无序集合) 3.4.1 结构图 3.4.2 相关命令 练习: 3.5 Zset(有序集合) 3.5.1 结构图 3.5.2 相关命令 练习 3.6 Hash 3.6.1 结构

    2024年02月16日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包