0基础C语言自学教程——第七节 初始指针

简介: 我们把计算机中的内存看作一条长街上的一排房屋。比如繁华大道上的多少多少号。每个房子可以容纳数据,并通过多少多少号来标识。

0基础C语言自学教程——第七节 初始指针


目录


内存和地址


指针引入


指针和指针类型


野指针


1. 指针未初始化


2. 指针越界访问


3. 指针指向的空间释放


如何规避野指针


指针运算


二级指针


指针是什么?


在讲解指针之前,我们需要探讨一个概念,那就是内存。

内存和地址

我们把计算机中的内存看作一条长街上的一排房屋。比如繁华大道上的多少多少号。每个房子可以容纳数据,并通过多少多少号来标识。

image.png



而在计算机内存中,计算机的内存由数以亿万计的位(比特位)组成,每一个位可以容纳0或者1.


如图,计算机由数以万计可以容纳1或者0的“房屋”组成。

image.png



而8个这样的比特位组成一个字节,每一个地址通过一个字节来标识。

微信图片_20221208182458.png



所以,我们也可以这样理解:把计算机中的内存划分成为一个一个小的内存单元,也就是字节。


为了存储更大的值,我们通常将2个或者更多的字节组合在一起,形成一个新的、更大的内存单位。比如,我们之前所说的,一个int类型占用4个字节(32位),一个double类型占用8个字节等。而如果是4个或者8个字节,通常都有且仅有一个地址。


而内存单元是有编号的,而这些编号,通俗一样上就是我们所说的地址。


每个地址标识一个字节,那我们就可以给(2^32Byte == 2^32/1024KB ==2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB)4G的空闲进行编址


在这些类型中,就可以通过0或者1来存储值。那么如果找到了这些元素的地址,就可以确定我们想要找的值了。


(plus:为什么会产生0和1?这里简单说一下,对于32位平台 - 有32根地址线 - 通电与否 - 代表着0/1。64位同理,有64跟地址线 -> 电信号就转换为数字信号)


但是,我们如果仅仅通过记住地址来去访问,是不是有点傻...所以,我们就引出了指针。


指针引入

指针理解的2个要点:


1. 指针是内存中一个最小单元(或者最大,取决于机器)的编号,也就是地址。(指针即地址)


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


举一个例子来看看:

image.png



如上面的图片所示,存储单元a中存储着数据100,它的地址位0x001132,我们把这个地址存储在p里面,那么,这里的p就是指针变量。p里面存放的就是a的地址。


理解了这么一对关系,实际上就抓住了关键。


我们再来明确一下各个量的含义:


0x001132是一个编号,也就是地址,而地址就是指针。


在这里的p,就是我们通常意义上的指针变量。


我们来用代码演示一下:

我们所打印出来的00B8FD18就是内存编号,就是a的地址。

我们还可以通过内存来查看:

这里的0x00EFFDCC就是它的地址,而0a 00 00 00就是它存储的值。


0a 00 00 00表示的是16进制数字,其中,0a表示一个字节,00 00 00 分别又表示着三个字节。


(我们只看前面四个字节的内容。后面的cccc表示未定义。具体的我们会在函数的栈帧的创建和销毁中去讲解)


那我如果这样:

那么这里的p便是我们所说的指针变量,其存储的就是a的地址。

我们打印p,可以看到,打印的就是a的地址。

上面的

int* p = &a.


以为p的类型为int*,而p是指针变量,存储的是a的地址。


那么,一个指针占多大内存呢?


我们在32位平台上来看一看:



可以看出,在32位平台上,一个指针占4个字节的大小。


对于64位平台,读者可以自行调试,其应占用8个字节的大小。


指针和指针类型

我们知道,数据的类型有整型、浮点型等等。那么对于指针有没有类型呢?


准确来说,是有的。


我们在上面定义指针类型的时候,我们留意到,是用int* 来定义的。依次类推,我们在定义其他类型指针的时候,也是用这种方法:


例如:

short* p1 = NULL;
char* p2 = NULL;
int* p3 = NULL;
float* p4 = NULL;
double* p5 = NULL;


所以,char*里存放的是char类型的数据;


         int* 里存放的是int类型的数据;


          以此类推...


那么同理,在对指针进行解引用的时候,是什么类型就能访问相应类型字节的大小的空间。


比如,对char*类型的指针进行解引用,就只能访问一个字节;


             int* 类型就只能访问四个字节。


           ....以此类推。


可以在内存监视中去查看。


野指针

什么叫野指针?


就是说指针所指向的位置是随机的、未确定的、没有明确限制的。


写出野指针会造成非常严重的后果。如果你的编译器语法检查足够严格,那么程序会直接崩溃掉。


那么,造成野指针的原因是什么呢?


1. 指针未初始化举个简单的例子,

举个简单例子

int* p;

这样定义一个未初始化的指针,如果其在未初始化的时候使用它,那么就会造成崩溃。

请看


int* p;

这样定义一个未初始化的指针,如果其在未初始化的时候使用它,那么就会造成崩溃。


请看:


为什么会这样?


原因很简单。因为 你的p不知道指向的是内存中的哪一块空间。它是随机的。在它不知道指向哪一块空间的情况下,对其解引用,就会造成 “不知道访问的是哪一块随机的地址” 这样一种尴尬。而这显然是不允许的。


2. 指针越界访问

指针的越界访问,与上面本质上是一样的。都是指针不知道指向了哪一块随机的地址。


举个例子:

int a[] = {0,1,2,3,4};
int* p = a;
p--;


一旦这样写,p就飞到九霄云外去了,不再在数组的“限制(控制)范围之内”


这个时候,p就是野指针。


3. 指针指向的空间释放

在动态开辟使用空间时,在free()以后,其free的只是指针后面的内容,而该指针本身就变成了野指针。(会在动态开辟内容章节详细讲解)


来看:

int* p = (int*)malloc(sizeof(int)*n);
free(p);


此时,p就是一个野指针。


所以通常情况下,我们都会再将p置空。


p = NULL;


如何规避野指针

几条建议:


1. 指针初始化


2. 小心指针越界


3. 指针指向空间释放即使置NULL


4. 避免返回局部变量的地址(这一条我们将会在下一章详细讲解)


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


指针运算

指针与指针之间,可以相减,但是不可以相加、相乘、相除;同时,指针可以加一个或者减去一个常数,但是不能够与常数相乘除。


并且,需要注意的时,两指针相减得到的并不是内存地址的差值,而是相差的数据类型的个数。具体来说,就是


(内存地址差值)/ (数据类型的大小)


另外,指针也可以比较大小。


还需要注意一点:


允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,


但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。


二级指针

这个其实很简单,也很好理解,说白了,就是一个指向指针的指针。


我们来看:

int a =  10;
int* p = &a;
int** pp = &p;


就是这个意思。


这里的pp就是一个二级指针。


目录
相关文章
|
2月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
51 0
|
5天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
20 2
|
2月前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
2月前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
2月前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
2月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
2月前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
2月前
|
C语言
C语言指针(3)
C语言指针(3)
14 1
|
2月前
|
C语言
C语言指针(2)
C语言指针(2)
15 1