指针---C语言(一)

简介: 指针---C语言(一)

前言:


 接下来我们进入C语言里的重头戏---指针。指针是一个很好用的东西,学好指针,无异于打下半片江山。


一.指针基础


 指针实际上是用来指向内存空间的一个变量。可能读者会觉得博主说得轻描淡写,我们先抛开先前对指针的恐惧,一步一步来讲,先从内存的基础讲起。


1.1内存单元

 内存是存取数据的一块大空间,我们知道,无论是什么事物,不好好利用都会有挥霍完的一天,相应的,要想高利用率的使用好内存空间,计算机前人们在设计的时候,就把内存空间划为一个一个小小的内存单元。


 那又如何区分这些长的一样的内存单元呢?在生活中,一栋栋商品房,房型差不多,如何让住户知道自己买的房间在哪里咧,假设有亲戚朋友要来我家,如何让他们知道我住哪里呢?我想,给个编号,给个地址不就好了~,现实中如此,计算机也如此,使用一个个编号给内存单元定义地址。


 这个编号是使用地址线(电线)的通电,不通电这两种状态转换成数字信号1,0给内存单元编号,这个编号也就是它们的地址啦。


 补充:32位电脑有32根地址线,每一根地址线可以产生0或1的数字信号,总共有2的32次方种组合,也就是可以管理2的32次方个内存单元。64位电脑就可以管理2的64次方个内存单元。


1.2内存单元和指针的大小

 那么一个内存单元多大合适呢?在以前我们常说4G、8G内存的电脑。我们姑且来算一下吧,假如一个内存单元只能存储一个bit位,那么32位机器内存大小为2的32次方个bit位:



  二进制第33位的1代表2的32次方,我们现在转换成Gb单位需要除以8(Byte)、除以1024(Kb)、除以1024(Mb)、除以1024(Gb)。



 由于程序员的除法取商,再除1024就是0了。所以现在是转换到Mb的单位,512Mb就是0.5G,这未免也太小了吧,听过最小的内存也是4G~,那一个内存单元从一个bit位变成一个字节呢?0.5G乘以8变成4G,可以接受~


 总结:计算机中一个内存单元是一个字节的大小。


 指针是存放内存单元地址的,一个地址的产生前面也说过。如果是32位平台,就用32根地址线生成32个数字信号来编号,那一个地址就是32个bit位,所以指针大小就是4个字节;如果是64位平台,指针大小为8个字节,这是固定的,不会根据数据类型改变指针大小。


 总结:指针大小如果在32位平台下是固定4个字节,在64位平台下是固定8个字节。


二.指针变量


 如何创建指针变量呢?请看值一段代码:

#include <stdio.h>
int main()
{
    int a = 0;
    int* pa = &a;
    *pa = 10;
    printf("%d\n", a);
    return 0;
}

2.1指针类型

 和创建普通变量是一样的,指针类型+变量名创建整型指针变量pa。&取地址操作符取出整型变量a的地址放到指针变量pa里面,*解引用pa的意思是找到pa存放的地址对应的内存单元,也就是找到了a,*pa相当于a。


 char*、short*、int*、float*、double*的大小分别是多少?都是4个字节的空间大小(32位),那char*类型的指针变量也可以存放整型变量的地址是毋庸置疑的,但这样做对吗?我们看代码:



 将a的地址放到char*的指针里面是能放进去的,只是编译器会有一个警告,报的是类型不兼容:



 这就是我们这里要讲的指针类型的意义:


指针变量的类型决定了指针解引用时改变多少个字节

指针变量的类型决定了指针加减运算时跳过多少个内存单元

 我们使用整型指针可以把-1完全变成0,而使用字符指针却改不成,这是为什么呢?请看:



 *pc只改了一个字节,(内存中用十六进制表示,两个十六进制位等于一个字节,16是2的四次方),所以a的补码为0xffffff00;打印的时候转换成原码~

  以上解释就是指针类型决定指针访问权限。还有一个指针决定指针加减运算跳过多少个内存单元的问题,博主简单说一下。


 一个指向整型的指针+1,指针变量里的地址会指向哪一个内存单元呢?我们看代码:



 整型a的起始地址是c4,本来a占有的内存单元有c4、c5、c6、c7这四个内存单元,一个内存单元一个字节,整型变量是四个字节大小嘛。然后使用它的首地址代表a的地址,整型值10就放在这四个内存单元里。p存放的值是a的地址,所以&a和p是一样的。


 打印p+1不是等于c5,而是c8,为什么呢?这里我们就得了解指针类型决定指针跳过多少个内存单元。可以这样理解,整型指针加1的意思是:指向下一个整型(当然下一个不一定是整型),只是这样说而已。



2.2野指针

 野指针就像野孩子一样,没有人管,这是非常危险的。野指针的常见情况如下:


没有初始化的局部指针变量。

指针指向的变量销毁掉了。

数组越界访问。

 局部变量没有初始化是随机值,一个局部指针变量如果没有初始化,那它也是一个随机值;指针变量是存放地址的变量,随机值存放在指针里面会被当成地址看待。如果此时不小心对指针进行了解引用操作,就会对不属于我们的内存单元里的内容进行修改,造成破坏,导致程序挂掉。


 指针指向的空间释放掉了,指针就变成了野指针。请看代码:



 a是test函数里的局部变量,在test函数里a存在,然后返回a的地址,a出了代码块,生命周期结束,被释放掉了,可是*p还是接收到a变量的地址,但a已经不属于我们了,此时p就是野指针。


 数组越界访问变成野指针在后面讨论指针和数组的关系时讲~


避免野指针

在创建指针变量的时候,如果不知道指向谁,初始化为NULL(空指针)

指针使用完后,赋值成空指针

在使用指针之前,用if测试指针现在放的是不是NULL,因为空指针不能解引用

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