学习阶段:高中信竞、大学编程。

前置知识:二进制与十六进制,C语言基础,数组。

指针初学可能比较难理解,我这篇文章尽量用通俗易懂的方式来讲解。

1. 指针概述

为什么有指针这个东西?因为指针很贴近计算机内部的实际工作原理,与内存实际的寻址方式类似。C语言可以说是高级语言中最贴近机器的语言,而像Python、JavaScript这种更亲和于人类的语言与机器的关系则比较远了,甚至它们本身可能还是用C语言写出来的呢。

指针可以形象地比喻为在内存中定位的导航员。内存那么大,怎么知道我需要的东西存在哪里呢?可以让指针来记录与导航。我们先来了解一下内存。

2. 预备知识

2.1 内存

研究过组装机、电脑配件的话,一定知道内存条这个东西。现在这个时代,一台家用电脑的内存一般是2GB、4GB、8GB、16GB、32GB、64GB等等。

把CPU比作干活的人,则内存就相当于工作台。CPU在跑的程序以及很多相关数据都存在内存内,这就相当于人在干活时要把相关资料放在工作台上使用。

内存可以看成是一个巨大的数组,我这里记为

memory[0..n]

memory的每一个单元存1B=8bit,memory[0]就是内存的第一个单元。这个中括号里面的数,即数组下标,被称为内存地址,简称为地址。我确定了一个地址,也就相当于确定了内存中的一个单元。

通常,我们说的32位机器,意思就是地址是32bit的,最大支持的内存是

memory[0x00000000..0xFFFFFFFF]

最小地址是0,最大地址是0xFFFFFFFF=2^32-1,最大支持

也就是说32位机器理论上最大支持4GB的内存,这就是它逐渐被淘汰的原因。

而64位机器理论上最大支持的内存是

这个量级远大于目前的需求,因此128位机器在相当长的时间内不会出现。

2.2 变量与数据类型

C语言有很多数据类型,不同的数据类型在内存中的占用空间存储格式也不一样。不同数据类型的存储格式比较复杂,这里不详述。我只谈谈不同的占用空间。

一个变量在内存中占用都是连续空间,记T类型的变量在内存中占用sizeof(T)字节的空间。当我声明一个T类型的变量a时,内存会寻找连续且可用的sizeof(T)个单元,把它们分配给变量a,比如说是memory[100..103]这4B的空间。此后我对变量a进行读写,也就相当于对memory[100..103]这4B的空间进行读写。

某些数据类型的占用空间:short短整形占用2B,int整形占用4B;float浮点形占用4B,double双浮点型占用8B;char字符型占用1B.

3. 指针

指针是一种特殊的数据类型,指针类型的变量应存储的是内存地址。在32位机器上,任何一个内存地址都是32bit=4B,故任何一个指针型变量都占用4B.

现在问题来了,指针指向内存中的一个单元,我怎么知道这个单元里面存的是什么东西,是什么类型的数据?因此,在声明指针变量的时候,也要声明这个指针指向数据的类型,比如int型指针、char型指针等。

3.1 指针的声明

在语法上,声明指针类型使用*符号,例如

int *a, b, *c; //a和c是指针,b不是指针
char *ch;

这两句代码声明了int*型的变量acint型变量b以及char*型变量ch. 根据语法,我们习惯上称T型指针为T*型,含义就是T*型变量是指针,其所指的相关内存单元存的是T型数据。 (注意,这里的b变量不是指针,仅仅为普通的int整形。)

3.2 指针的使用

指针有很多种使用方式,包括动态申请内存、函数地址传参等等。我这里仅介绍最简单的使用方式。我提供一份例程,可直接从例程中学习指针的声明与使用。

例程:

int x=1, y=2; //声明x与y并赋初值
int *p=&x; //声明p且p指向x
*p=11; //p修改x
p=&y; //p指向y
*p=12; //p修改y
printf("x=%d, y=%d", x, y); //打印x与y

第一行,在内存中申请连续的4B区域存入int型数据1,记为变量x;再在内存中申请连续的4B区域存入int型数据2,记为变量y. 假设x对应内存区域memory[100..103]y对应内存区域memory[200..203]. 第一行执行完毕,内存如图1所示:

图1 第一行执行完毕

第二行, 在内存中申请连续的4B区域存入int*型地址数据100,记为变量p. 这里&符号是取地址运算符,表示取变量x的首地址,在本例中就是100. 这一行代码是声明指针同时赋初值,相当于以下两行代码:

int *p;
p=&x;

第二行执行完毕,内存如图2所示(100的十六进制是0x64):

图2 第二行执行完毕

第三行,将p所指的地址起4B空间内存入int型数据11. 这里*解地址运算符, 表示取得指针所指的内存空间。 第三行执行完毕,内存如图3所示:

图3 第三行执行完毕

如果第三行改为执行p=(int*)11;,则是先把int型数据11强制转换为int*型数据11,然后赋值给p,如图3.2所示:

图3.2 第三行改为执行p=(int*)11;

此时p所指的内存空间不一定是可用的。因此像这样直接给指针赋值一个常数的情况非常罕见。

第四行,py的首地址。第四行执行完毕,内存如图4所示:

图4 第四行执行完毕

第五行,把变量y的值改为12. 第五行执行完毕,内存如图5所示:

图5 第五行执行完毕

第六行,打印xy的值,打印结果应为:

x=11, y=12

4. 多级指针

指针也可以指向指针,称为多级指针。

例程:

int x=1;
int *p=&x;
int **p2=&p;

这里p2就是一个二级指针,它的类型是int**,它也存了一个地址,但是这个地址是某个int*型变量的地址,在这里是存了int*型变量p的地址。

假设x的首地址是0x10,p的首地址是0x20,那么内存的情况如图6所示:

图6 多级指针示例

三级、四级等等更多级的指针也是存在的,但是几乎不会用到。二级指针一般只在二维数组中会用到,其他情况也很少见。尽量不要使用多级指针,不然真的容易弄晕自己。

5. 答疑

5.1 星号*的不同作用

在指针声明、数据类型中,*表示是指针类型;在已声明变量前面的*是解地址运算符,比如说*p就是用p的内容求得其所指的区域;当然,*还有算数乘法等含义。

c语言 指针_C语言——指针相关推荐

  1. sdh管理单元指针_C语言学习|指针的介绍

    指针是C语言提供的一种特殊而又有非常重要的数据类型. 联合使用指针和结构体这两种数据类型可以有效地表示许多复杂的数据结构,如队列.堆栈.链表.树.图等. 指针这个内容为什么那么的重要? 1.指针为函数 ...

  2. c语言 指针_C 语言指针详解

    (给CPP开发者加星标,提升C/C++技能) 作者:C语言与CPP编程 / 自成一派123(本文来自作者投稿) 1为什么使用指针 假如我们定义了 char a='A' ,当需要使用 'A' 时,除了直 ...

  3. c语言指针++_C ++此指针| 查找输出程序| 套装1

    c语言指针++ Program 1: 程序1: #include <iostream> using namespace std; int main() { int A = 10; this ...

  4. c语言 指针_C语言野指针以及非法内存操作

    如果一个指针指向的内存没有访问权限,或者指向一块已经释放掉的内存,那么就无法对该指针进行操作,这样的指针称为野指针(Wild Pointer). 指向没有访问权限的内存 请看下面的代码: #inclu ...

  5. C进阶_C语言_函数与指针_C语言指针进阶

    上一篇博客http://t.csdn.cn/GYCiM 我们了解了指针相关知识,今天来了解函数和指针的关系. 目录 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 qsort 冒泡排序模拟实 ...

  6. *(p+i) ,C语言数组指针_C语言中文网

    一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址.所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址. 字节是内存中的最小可操作单位,我们 ...

  7. c语言memset清空指向数组的指针_C语言中数组和指针的关系

    数组的数组名其实可以看作一个指针.看下例: 1.    int array[10]={0,1,2,3,4,5,6,7,8,9},value; 2.    value=array[0]; //也可写成: ...

  8. 出参传递数组指针_C语言指针重难点详解

    1为什么使用指针 假如我们定义了 char a='A' ,当需要使用 'A' 时,除了直接调用变量 a ,还可以定义 char *p=&a ,调用 a 的地址,即指向 a 的指针 p ,变量 ...

  9. c语言关键字_C语言初学者必须掌握的关键字!

    相信这么努力的你 已经星标了我 老九学堂 你身边的IT导师 其实小伙伴在写代码的时候,关键字还是用的比较多的,  今天大雄主要就平常中用到的常用关键字进行总结,便于小伙伴们更全面的理解其在代码中的意图 ...

最新文章

  1. mysql delete 注意
  2. java元婴期(21)----java进阶(spring(5)---事务管理AOP事务管理(全自动)spring整合Junit)
  3. Linux 编译安装内核
  4. LeetCode - 35. Search Insert Position
  5. 深度学习实战 | 使用Kera预测人物年龄
  6. 基于Doxygen的C/C++注释原则
  7. 计算机病毒解析与防范结束语,2016年04月30日计算机病毒解析与防范题纲_向必青.doc...
  8. windows卸载服务
  9. 如何裁剪PDF文件的页面大小
  10. 计算机增加一个硬盘怎么设置方法,电脑加硬盘【操作教程】
  11. Scratch少儿编程案例-算法练习-存款收益计算
  12. 使用PowerShell替代WinDbg在高分辨率笔记本下调试、排错
  13. AutoJs学习-悬浮单任务计时器
  14. tomcat项目在Linux下生成文件路径错误问题
  15. 一盆惨遭毒手的肉——记,那一次和小鲜肉的邂逅
  16. 【数据科学】数据可视化指南
  17. 留学生cs辅导 csp-j/s 数据结构与算法
  18. Dual Processor vs Dual Core
  19. php循环结构,php学习之 循环结构实现代码
  20. centos用户账户管理

热门文章

  1. make时候说找不到makefile_找不到对象,应不应该接受相亲?听听三个过来人怎么说...
  2. python浅拷贝的说法_Python中List的复制(直接复制、浅拷贝、深拷贝)
  3. C如何将二维数组作为返回值
  4. 买服务器带操作系统,买服务器带操作系统
  5. mysql数据库突然连不上了_mysql数据库突然连接不上去
  6. burpsuite全套使用教程
  7. React antd Descriptions span属性无效问题
  8. 为自己写程序之JavsScript代码段测试器
  9. WebUploader点击上传文件选择框会延迟几秒才会显示
  10. js基本包装类型和引用类型