【C语言】C语言成长之路之初阶指针.( Ꙭ)

❤️前言

大家好呀ʕ•ﻌ•ʔ!,今天我为大家带来的是一篇关于我最近刚学的C语言指针方面的博客。指针和结构体都是C语言独有的特殊符号,可以说学好了它们,你就拿下了C语言的半壁江山。希望大家能喜欢我的这篇文章(•̀ᴗ• )ya~ 😘 😘 😘

👉 一、对于指针及指针变量的理解

🔎 1、地址(指针)

在程序运行时我们会调用内存空间来完成一系列的操作,那么就像我们在拜访别人的家时需要知道对方的地址那样,当我们需要访问内存空间时,我们就需要知道其对应的地址(指针)。比如我们在创建一个变量时就需要申请一块内存空间来存放它,这些内存空间中的每个小单元(一个字节)都对应着一个地址(指针)。

🔑 内存和编址

💡这里补充一些关于内存和编址的知识,便于大家理解指针的知识:

我们以32位机器为例进行讲解,32位机器的内存以32根地址线进行编址,地址线分别以高电平1和低电平0的电信号来显示状态,这些不同的状态可以带我们寻址不同的空间,如下图:

地址线

由于地址线的状态以高低电平的两种形式显示,那么32根地址线的状态便可以表示为32位的二进制数:
二进制数表示地址

依据这些二进制数,我们便可以寻址内存单元并访问内存单元,经过仔细地运算和权衡,最终我们可以发现一个字节给一个对应的地址即——一个地址管理一个字节的空间大小是合适的,这样我们的寻址空间便是4GB的大小。

🔎 2、指针变量(指针)

温馨提示:我们在口语中常常直接将指针变量称为指针,所以有的时候大家需要分辨一下“指针”指的是变量地址还是指针变量。(为防止大家搞混指针和指针变量,在本文中,我会将指针变量称为指针或者直接称为指针变量内存地址就直接称为地址)

想必经过上述的文章说明,你也已经对地址和指针有了一定的了解。那么我们继续来聊存放地址对应值的变量——指针变量

我们知道,在32位机器上,地址是由32位的二进制数字表示,那么我们就可以推断出32位机器上一个指针变量的大小是4个字节(即32bit / 8 = 4byte),类比到64位机器上指针变量的大小便是8个字节。ps:64位机器以64根地址线进行编址。

注意,接下来我的讲解都以32位机器作为标准。

32位机器上,管理1个字节大小的地址却用固定4个字节大小的指针变量来存储,那么我们在利用指针访问变量时,难道要用多个指针变量来存储对应的多个地址吗(以int类型为例,难道我们要用4个指针变量才能访问这个变量吗)?。

用过指针的友友应该知道,我们只需要用一个指针变量就可以了,那么一个指针变量是如何完成这一点的呢?

.
答:在为创建的指针变量初始化时(不包括初始化为NULL),我们的指针变量只记录对应变量的低地址,这点和数组名即为数组首元素地址有一定的相似性,这样我们就能保证在机器不变的情况下,指针的大小不变:
狮子亲爪画图

👉 二、指针类型

在了解了上述的知识之后,你是否对指针类型存在的意义产生了疑惑?现在我们继续聊指针类型的相关内容:

指针类型的意义

🔎 1、访问视角的大小

  1. 指针类型决定了指针解引用的权限有多大,即能够访问多少字节的数据(或者理解为访问变量的视角大小)。

如:char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

🔎 2、针对指针的变化幅度

  1. 决定了指针向前向后变化一个单位的大小(可以理解为走一步或退一步的步幅)

以下题为例:

//请你想想这段代码最后打印出的内容
#include <stdio.h>
int main()
{
  int arr[] = {1,2,3,4,5};
  short *p = (short*)arr;
  int i = 0;
  for(i=0; i<4; i++)
  {
    *(p+i) = 0;
  }
   
  for(i=0; i<5; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}
//答: 0 0 3 4 5

此题中,我们以 short* 的指针类型来访问更改我们创建的一个整形数组中的元素。(注:short 类型占2个字节大小)用short*类型的指针改了四个0,移动一个单位即是移动两个字节,最后就是把1,2两个元素改成了0。

👉 三、野指针

野指针指 ”指向的位置是不可知的(随机的、不正确的、没有明确限制的)的指针“

造成野指针现象的原因大致有:
1.局部变量未初始化

2.越界访问

3.指针指向空间释放

如何规避野指针

1.指针初始化
1)当前不知道要初始化为什么地址的时候,直接初始化为NULL。
2)明确知道初始化的值。

2.避免指针越界访问
由于C语言本身不会检查数组越界的行为,所以我们在编写代码的时候要注意是否出现越界访问的情况。

3.指针指向空间释放时及时置NULL。
例:当空指针被函数调用后需要置空,否则原来的记录的地址会留在指针中。

4.指针使用之前检查有效性。

👉 四、指针运算

  1. 指针 ± 整数

地址由低到高变化,变化单位为指针类型的大小

  1. 指针 - 指针

指针减指针得到之间的元素个数。(指针和指针相减的前提是两个指针指向一块空间)

  1. 指针的关系运算

关系运算中值得注意的是,
引用

👉 五、指针与数组

在数组中,每个元素对应着一个地址,而这些地址依照下标顺序由低到高排列,即下标零0对应元素地址(也即首地址)是最低地址。

具体运用以经典的C语言字符串逆序代码展现:

#include <stdio.h>
#include <string.h>
void rev(char* str)
{
	int len = strlen(str);
	char* left = str;
	char* right = str + len - 1;
	while (left < right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
int main()
{
	char str[10000] = { 0 };
	gets(str);
	rev(str);
	printf("%s", str);
	return 0;
}

👉 六、二级(多级)指针

我们的指针变量也是变量的一种,那么它也会被存储在一块由地址管理的内存空间中,这样我们也可以用指针来指向这个指针变量。这样我们就得到了二级(多级)指针了。

就像这样(՞• •՞):
阿尼亚
注意解引用符( * )是可以叠加使用的,也就是说可以由二级指针解引用两次得到一级指针对应变量。

需要注意的一点是二级指针创建时需要使用两个(*),像这样int** pp = &p;

👉 七、指针数组

指针数组顾名思义即为以指针作为元素的数组,下面演示指针数组的创建:

例:整型指针的数组

int* parr[5]
//parr即为整形指针数组,可存5个整型指针

指针数组的应用:

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

运行结果:
运行结果
这里演示的是指针数组存数组名(即数组首地址)的应用,感觉上与二维数组有一定的相似性,二维数组存储数组作为元素,而指针数组存储数组名也可访问对应的数组。

🍀 结语

在以上的文章中,我们一起学习了C语言的 初阶指针 的知识,阅读了上述内容后,希望大家能够或有所得,学有所得后我相信大家肯定能通过指针来完成一些新的代码 ๐•ᴗ•๐ !

最后,希望正在看我的博客的你,能够天天进步,事事顺心,每天都有开心的好心情呀₍ᐢ •͈ ༝ •͈ ᐢ₎♡

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发呆的yui~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值