深入了解指针(一)

发布时间:2024年01月16日

前言

指针可是数据结构的基础,其内容及重要又繁多,之前没有时间整理出来,现在放假了怎么说也要写一个,既是对前面的总结和梳理,也可以用来以后的查找知识,ok,废话不多,直接启动。

指针是什么

指针是C语言中的一种特殊数据类型,它存储了一个变量的内存地址。通过指针,我们可以直接访问和修改该内存地址上存储的值。指针变量本身也有自己的存储地址,而指向指针变量的存储地址就被称为指针的指针,即二级指针。多级指针的定义就是定义时使用多个"*"号。

1内存和地址

1.1内存

我们知道你的代码中的变量常量都是放在内存中的,我们电脑大多是4g或8g内存,这些内存空间被平均分了许多份,每份大小是1个字节

下面是常见的内存大小单位以及换算

我们可以把整个内存当成一个酒店,每个空间当作一个房间,那么每个房间的门牌号就是地址,我把地址告诉你了,你自然就能找到那个房间了。而在C语言中地址就是指针。

1.2地址的写法

我们知道你电脑cpu和内存要互相协同?作的。所谓的协同,?少相互之间要能够进?数据传递。那么如何通信呢?答案很简单,?"线"连起来,我们今天关??组线,叫做地址总线。

我们可以简单理解,32位机器有32根地址总线,每根线只有两态,表?0,1【电脉冲有?】,那么
?根线,就能表?2种含义,2根线就能表?4种含义,依次类推。32根地址线,就能表?2^32种含
义,每?种含义都代表?个地址。如此一来每个字节大小的空间就被编好地址了。
地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传?
CPU内。
当然了,为了书方便我们写地址是以16进制写的,对32位机器如果某个空间地址是
10000000 10000000 10000000 10000000
换算成16进制就是0XF0 F0 F0 F0? ? ? ?前面的0X表示这个数是16进制,且字母大写
取地址操作符(&)
理解了内存和地址的关系,我们再回到C语?,在C语?中创建变量其实就是向内存申请空间,?如:
上述的代码就是创建了整型变量a,内存中申请4个字节,?于存放整数10,其中每个字节都
很明显他们里面存放的值分别是0a? ? 00? 00? 00,用小端换算成10进制就是10
那我们如何能得到a的地址呢? 用到操作符&
当然了这里的地址是4个地址中最小的那个,你可以理解为从这个地址开始向后4个字节都是a的空间,于是乎我们顺藤摸瓜就能找到另外三个了
那我们通过取地址操作符(&)拿到的地址是?个数值,?如:0x006FFD70,这个数值有时候也是需要

2指针变量和地址

2.1取地址操作符&和指针变量

将指针存储起来,可以?便后期再使?的,那我们把这样的地址值存放在哪?呢?答案是:指针变量中,用什么方法呢?答案是取地址操作符
#include<stdio.h>
int main()
{
?? ?int a = 10;
?? ?int* p = &a;
?? ?return 0;
}
指针变量也是?种变量, 这种变量就是?来存放地址的,存放在指针变量中的值都会理解为地址。
指针变量的类型:对应数据类型加上一个*
int对应int*
char对应char*
double对应double*
以此类推
可以理解为*是在说明他是个指针,而前面的int则说明它指向的地址里的数据是int类型,这个地址的值就被存到这个指针变量里了

2.2解引用操作符*

我们将地址保存起来,未来是要使?的,那怎么使?呢?
这里就要用到解引用操作符*了
和明显我们通过*p找到了a并且打印了出来,
这里我们通过指针p修改了a的值
可能有同学会觉得麻烦,感觉不如直接打印a或者修改a, 但以后函数的传值与传址就会明白了

2.3 指针变量的??

前?的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后
是1或者0,那我们把32根地址线产?的2进制序列当做?个地址,那么?个地址就是32个bit位,需要4
个字节才能存储。
如果指针变量是?来存放地址的,那么指针变的??就得是4个字节的空间才可以。
同理64位机器,假设有64根地址线,?个地址就是64个?进制位组成的?进制序列,存储起来就需要
8个字节的空间,指针变的??就是8个字节
x64环境下的
x86环境下
结论:
? 32位平台下地址是32个bit位,指针变量??是4个字节
? 64位平台下地址是64个bit位,指针变量??是8个字节
? 注意指针变量的??和类型是?关的,只要指针类型的变量,在相同的平台下,??都是相同的。

3. 指针变量类型的意义

3.1 指针的解引?

x会将a的4个字节全部改为0,y只是将b的第?个字节改为0。

结论:指针的类型决定了,对指针解引?的时候有多?的权限(?次能操作?个字节)。
?如: char* 的指针解引?就只能访问?个字节,? int* 的指针的解引?就能访问四个字节。

3.2void* 指针

在指针类型中有?种特殊的类型是 void* 类型的,可以理解为?具体类型的指针(或者叫泛型指
针),这种类型的指针可以?来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进
?指针的+-整数和解引?的运算。
int main()
{
?? ?int a = 10;
?? ?void* p = &a;
?? ?*p = 0;
?? ?p++;
?? ?return 0;
}
?般 void* 类型的指针是使?在函数参数的部分,?来接收不同类型数据的地址,这样的设计可以
实现泛型编程的效果。使得?个函数来处理多种类型的数据,

4. const修饰指针

4.1?const修饰指针变量

int main()
{
?? ?int a = 10;
?? ?const int* p = &a;
?? ?*p = 5;
?? ?return 0;
}
这时无法通过*p修改a的值
这时不能改变p的值
但是你可以通过二级指针的方法绕过去,可事实上不该这样做,因为他既然被const修饰了就说明写他的人不希望它被改变,
int main()
{
?? ?int a = 10;
?? ?int b = 5;
?? ? int* const p = &a;
?? ? int** b = &p;
?? ? int*x = &b;
?? ? b = &x;
?? ?return 0;
}
结论:const修饰指针变量的时候
? const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本?的内容可变。
? const如果放在*的右边,修饰的是指针变量本?,保证了指针变量的内容不能修改,但是指针指
向的内容,可以通过指针改变

5. 指针运算

指针的基本运算有三种,分别是:
? 指针+- 整数
? 指针-指针
? 指针的关系运算

5.1 指针+- 整数

因为数组在内存中是连续存放的,只要知道第?个元素的地址,顺藤摸?就能找到后?的所有元素。

5.2 指针-指针

我们通过这个实现了strlen函数
//指针的关系运算
#include <stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 while(p<arr+sz) //指针的???较
 {
 printf("%d ", *p);
 p++;
 }
 return 0;
}

5.3 指针的关系运算

//指针的关系运算
#include <stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 while(p<arr+sz) //指针的???较
 {
 printf("%d ", *p);
 p++;
 }
 return 0;
}

6. 野指针

概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

6.1 野指针成因

1. 指针未初始化

# include <stdio.h>
文章来源:https://blog.csdn.net/2301_79551553/article/details/135616081
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。