【C语言】带你完全理解指针(一)

本文介绍了指针在C语言中的基本概念,包括指针的定义、类型、大小、野指针的成因及规避方法,以及指针运算(如指针加减整数和比较)、数组与指针的关系和二级指针、指针数组的运用。重点强调了指针变量的用途和初始化重要性。
摘要由CSDN通过智能技术生成

目录

前言

一、指针是什么?

 指针变量

 二、指针和指针类型

 1、指针的大小:

2、指针类型的意义

 三、野指针

1、野指针成因

 2、如何规避野指针

 四、指针运算

1、指针±整数

2、指针-指针

3、指针的关系运算(比较大小)

五、 数组和指针

 六、二级指针

七、指针数组


前言

本篇是对指针知识的初级理解,后续还会有文章带大家了解指针

一、指针是什么?

指针是什么?

1、每个内存单元都有一个编号,把内存单元的编号就称为地址(地址也叫指针)

一个内存单元是一个字节

2、指针是内存中一个最小单元的编号,也就是地址

3.平时口中说的指针,通常指的是指针变量,是用来存放内存地址的变量

4.指针的大小在32位平台是4个字节,在64位平台是8个字节。

 

原因:在32位的机器上,地址是32bite组成二进制序列,因为32bit就是4字节那地址就得用4个字节(1byte = 8 bit)的空间来存储,

所以 一个指针变量的大小就应该是4个字节。

那如果在64位机器上,有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。 )

指针就是地址

 指针变量

我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量,简而言之就是一个变量,变量里面放的是地址

写c语言程序的时候,创建的变量,数组等都要在内存上开辟空间

a变量占4个字节,这里把a4个字节的第一个字节的地址放在p变量中。

指针变量在32位的平台是4字节,在64平台是8字节

pa的类型是int **意味着pa是指针,int意味着pa指向的那个变量是int类型

总结;指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。 

 二、指针和指针类型

 1、指针的大小:

在32位平台是4个字节,在64位平台是8个字节。

当不知道给这个指针赋值什么时,就赋值为NULL 。(避免野指针后面会讲)

sizeof 返回值的类型是无符号整型 unsigned int,严格意义上打印时应该用%u,不能用%d,%zu打印最准确,%zu本身就是给sizeof准备的一种格式打印。

 

2、指针类型的意义

整型有类型 int char short…,指针变量也有类型

讲解:

意义1:指针的类型决定了指针在被解引用的时候可以访问几个字节(指针的权限)

Int*的指针解引用访问4个字节

Char*的指针解引用访问1字节

 意义2:指针类型决定指针加一减一操作时的步长(跳过多少字节)

指针的类型决定了指针±1操作的时候,跳过几个字节,即指针的步长。
如果是int的指针,+1跳过4个字节
如果是char
的指针,+1跳过1个字节
当然,指针不仅可以±1,指针±整数时也很类似。

前后是统一的,解引用访问多少字节,加一减一跳过几个字节。

type* p;

跳过的是:n*sizeof(type)这么多个字节。

 三、野指针

概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的),比如一个全部变量不初始化。

1、野指针成因

指针未初始化

 局部变量指针没有初始化,默认是随机值

 指针越界访问

 数组只有10个元素但是通过指针访问了不属于这个数组的空间所以是越界访问

指针所指向的空间释放了

a是一个局部变量,进入函数就创建,离开函数则还给操作系统

 2、如何规避野指针

  1. 指针初始化
  2. 小心指针越界
  3. 指针指向空间释放及时置NULL
  4. 避免返回局部变量的地址
  5. 指针使用之前检查有效性
int main()
{
	int a = 10;
	int* p = &a;

	int* ptr = NULL;//ptr是一个空指针,没有指向任何有效的空间。这个指针不能直接使用
	//int* ptr2;//野指针

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

	return 0;
}

明确知道指针应该初始化为谁的地址,就直接初始化

不知道指针初始化为什么值,暂时初始化为NULL

 四、指针运算

1、指针±整数

将数组中的元素都赋值为1

不使用下标访问操作符

int main()
{
	int arr[10] = { 0 };
	//不使用下标访问数组
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		*p = 1;
		p++;//p = p+1
	}
	p = arr;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//p+i
	}

	/*for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}*/

	return 0;
}

 讲解:使用指针来实现给数组里面的元素赋值。因为p是指针,可以通过指针加上数字找到下一个元素的地址之后解引用来赋值。

 //int arr[10]
//int* p = arr;
//*(p+i) == arr[i]

*(p+i)和arr[i]是一样的。arr是数组名是首元素的地址

 来看这些等价的表达:

arr[i]==*(arr+1)==*(i+arr)==i[arr];

可能对最后一个会不太理解。

2+3->3+2;[]是操作符而已和加号一样

arr[i]-->i[arr],arri只是两个操作数而已,和32一样

 

 指针之间是可以比较大小的;


 

2、指针-指针

指针 - 指针的绝对值得到的是指针和指针之间元素的个数

但是指针相减有前提:要指向同一块空间

例子:自定义函数求字符串的长度

方法一:

方法二:递归:

方法三:指针-指针(得到指针和指针之间元素的个数,可以得到字符串的长度)

指针-指针得到的数值的绝对值:是指针和指针之间的元素个数
指针-指针运算的前提条件是:指针和指针指向了同一块空间。

先保存首元素的地址,之后返回末尾和首元素地址的差

因为s在找到字符串结尾的'\0'时还会做一次加1操作,所以在计算长度时应该减去这一次额外的加1操作

这个就多加了一次,s++还是a的地址因为是后置加加,解引用用完之后s到下一个值的地址

*s++这个操作在C语言中会先执行 s++这个操作,然后才会执行解引用操作。. 这是因为在C语言的操作符优先级中,后缀自增++的优先级(级别2)要高于解引用*(级别3)。所以,先对 :执行后缀自增操作,使得:指向下一个元素,然后再进行解引用操作取出 s指针指向的内容。
因此,*s++意味着先取出当前 :所指向的元素的值,然后再将 :让其指向下一个元素


 

3、指针的关系运算(比较大小)

最后两个指针相等了

 

五、 数组和指针

指针变量就是指针变量,大小是4或者8,用来存放地址的

数组就是数组,数组一块连续的空间,可以存放1个或多个类型相同的数据

联系:数组名是数组首元素的地址也就是指针

当我们知道数组首元素的地址的时候,因为数组是连续存放的,所以通过指针就可以遍历访问数组

数组是可以通过指针来访问

int arr1[10]

int ar2[8];这两个数组的类型一样吗? 

 讲解:不一样去掉数组名就是类型,一个是int[10],一个是int[8]

 六、二级指针

创建一个变量p,他是一级指针,变量实在内存中开辟空间的,它自己也有自己的地址

 

这个*说明p是指针,前面的int说明p指向的那个变量的类型是int

同理*说明pp是指针,int*说明pp指向的变量的类型是int*

 

 

 

七、指针数组

指针数组是指针还是数组?

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

整型数组   存放整型的数组

字符数组   存放字符的数组

指针数组   存放指针(地址)的数组

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	//指针数组
	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("%d ", parr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

 这个parr就是指针数组,它的每个元素都是char*类型。长这样char* parr[]

 

 这个parr就是指针数组,它的每个元素都是char*类型。长这样char* parr[]

 

Parr[1]这个数组的第一个元素是arr1arr1又是数组名是arr1数组的起始地址(第一个元素的地址)

为什么是打印整个数组呢,我们看个简单的例子

怎么样是不是就明白了

用一个指针数组模拟出一个二维数组

等价的写法

后面还会学习指针数组的~

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值