C语言指针入门 《C语言非常道》
C语言指针入门 《C语言非常道》
作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。
但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是:
李忠老师官网
最棒的是,有配套的教学视频,可以试看。
试看点这里
接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非常道》,如果读起来吃力的话,建议看视频。
文章目录
- C语言指针入门 《C语言非常道》
- 初识指针
- 取地址运算符和指针变量的声明
- 指针指向什么类型很重要
- 解引用运算符
- 总结与补充
指针是 C 语言的难点,也是亮点。有人说如果不懂指针,那就不算是掌握了 C 语言。
作为一个嵌入式软件工程师,我认为指针是 C 语言的杀手锏,离开了它,C 语言不可能在嵌入式领域“一览众山小”。
好了,进入正题。
初识指针
int a = 5;
这句话定义了 int 类型的变量 a,并给它赋值 5;
在计算机执行这条语句的时候,会为变量 a 分配内存。
从此,这块内存就和 a 联系起来了,可以说变量名 a 就是这块内存的化身。目前,这块内存的存储值是 5。
如果你要把存储值修改为 8,你可以写
a = 8;
程序执行的时候,它自然会根据变量名 a 找到这块内存,把里面存储的值改为 8.
如果不知道这块内存的名字是 a,你还能修改它的存储值吗?
方法还是有的,那就是通过“指针”。
其实在计算机眼中,内存是有地址的。要访问某个内存单元,需要知道它的地址。如果把内存比喻成一排房子,那内存地址就是房子的门牌号码。
如上图所示,右边标注的就是内存的地址(假设一个格子占 4 字节),变量 a 的内存地址就是 12.
如下图所示,假设有个变量 b,它里面的内容刚好是变量 a 的内存地址(12),那么顺着这个地址就可以找到变量 a.
红色箭头表示顺着变量 b 的值(其实是 a 的地址——12)找到了变量 a.
你瞧,b 代表的值,像指针一样,指向那个地址上的变量,鉴于这种类比特别形象,C 语言引入了指针类型,简称指针。图中的变量 b 就是指针类型。
取地址运算符和指针变量的声明
有人问,你怎么知道变量 a 的地址是 12 呢?
C 语言里面有个运算符——“&”,叫“取地址运算符”,用于取得某个变量的地址。要得到变量 a 的地址,可以这样写:&a
要想把 a 的地址保存在 b 中,可以这样写:
int *b;
int a = 8;
b = &a;
第 1 行,定义了一个变量,变量名字是 b.
第 3 行,获得变量 a 的地址,把这个地址存储在变量 b 中。
int *b;
应该这样理解:
首先,从标识符开始读,因为标识符 b 的右边是分号,所以要向左读,左边是 *
,意思是指针,所以读做 b 的类型是指针;
其次,对于指针这种类型来说,它指向的类型也很关键,我们继续向左读,遇到了“int”,所以读“指向 int”
把粗体字连起来:b 的类型是指针,指向 int。
再比如:
int * p; // 注意,* 和 p 之间也可以有空格
这句话定义了一个指针类型的变量 p,准确地说,p 的类型是指针,指向 int 类型,即 p 是一个指向 int 类型的指针变量。
上图来自李忠老师的书——《C语言非常道》,告诉我们如何读指针类型的声明或定义。
注意:指针类型是个统称,根据它所指向的类型,可细分为指向 char 的指针、指向 short 的指针、指向 int 的指针,等等。
要把变量 x 的地址保存在一个变量里,这个变量的类型必须是指针类型,而且,指针指向的类型必须和 x 的类型一致。例如,如果 x 是 char 类型,那么指向 x 的指针要声明为 char * p;
如果 x 是 double 类型,那么指向 x 的指针要声明为 double * p;
指针指向什么类型很重要
有人会说:指针变量就是存储地址的变量,顺着这个地址,可以找到另一个变量,这个可以理解,但是为什么要强调指针指向的类型呢?
在 C 语言里,取地址运算符 &
的结果(值)并不单纯是一个地址,而是一个包含了类型信息的地址。
例如前面提到的 &a
,它确实可以计算变量 a 的地址,但是这个地址还包含了一个信息,即这个地址是用于访问 int 类型变量的(因为 a 是 int 类型)。
为什么要附加一个类型信息呢?
前面我画的内存图示比较粗,现在细化一下。假设我的实验环境下,int 类型的变量占 4 个字节,short 类型占 2 个字节,char 类型占 1 个字节。现在定义 3 个变量,运行时的内存如下图所示:
右边标注的是内存地址,每个格子代表一个字节,你会发现内存地址是按照字节来编号的。
对于变量 a ,它占据了 4 个字节,即内存 12、13、14、15.
有人会问,那 a 的地址是多少?是 12 还是 13,还是 14,或者 15?
按照规定,a 的地址是它所占内存中编号最小的那个,即 12.
如果指针不含有类型信息,仅仅是一个地址(比如 12),那么顺着这个地址去访问内存,到底访问多少字节呢?
举个例子,假设要修改 a 的值为 100,如果不是按照 4 个字节来写,而是按照 8 个字节来写,那肯定会把变量 m 和 n 的值给覆盖,这肯定不行。
所以,指针必须含有类型信息,这样才能知道此地址指示的变量占用多大的内存,访问的时候才不会出错。
如图所示,一旦知道了指针 b 所指向的类型是 int ,在访问 a 的时候,就可以锁定 12~15 这四个字节。
所以,一个指针是包含 2 个信息的:
- 指针代表的地址。如图中的红色箭头,这个地址可以让我们定位到内存 12,但是我们只知道从 12 开始,不知道在哪里结束。
- 指针指向的类型。类型确定了,占多少个字节就确定了。如图中的红色虚线框,这个类型可以让我们锁定从 12 开始的 4 个字节( int 占 4 个字节)。这 4 个字节,就是变量 a 所占的内存。
基于以上 2 点,通过指针 b 间接访问变量 a 成为可能,堪称完美。
解引用运算符
如何通过 b 修改 a 的值呢?假设要通过 b 把 a 的值改为 100,可以这样写:
int *b;
int a = 8;
b = &a;
*b = 100;
第 4 行,b 左边的这个 *
,不代表指针,而是解引用运算符,也叫间接运算符。
前文已经说过,&
运算符用于取得变量的地址,而 *
运算符则根据一个地址来得到那个变量本身。也就是说, b 指向了哪个变量,*b 就代表那个变量。
所以,第 4 行的 *b = 100;
就相当于 a = 100;
*
和 &
在一起可以互相抵消, 例如 *&a
就等价于 a
,你想,&a
表示一个指向 a 的指针,指针左边加一个 *
,就得到此指针指向的变量,于是又成了 a;
另外,&*b
等价于 b,因为 *b
就是 a,而 &a
就是 b.
总结与补充
相信有了前面的铺垫,你再读教科书上的文字会很有感觉。
以下几点是总结和补充。
一元
&
运算符称为取地址运算符,它需要一个右操作数,这个右操作数必须是变量或者函数。这是很自然的,只有内存中的变量或者函数才有地址,你不能取一个常量的地址,比如& 250
,这很荒唐。 一元*
运算符则根据一个地址来得到那个变量(或者函数)本身 。(注意:指向函数的指针是进阶内容,初学者可以忽略。)“指针”这个词其实有多种含义,需要根据上下文来区分。
1). 是一种类型,比如整形、浮点型等。指针这种类型特殊在它的值是一个内存地址,顺着这个地址可以找到另一个变量。
2). 为方便起见,人们有时候也把指针类型的值叫作“指针”。 比如说, C 语言规定, 如果操作数的类型为 T,则一元 & 运算符的结果是指向 T 的指针。在这里,“指针”应该理解为“指针类型的值”。
3). 人们更经常地把指针类型的变量叫作指针,相对于“p 是一个指针类型的变量”,人们更喜欢说“p 是一个指针”。
为了还原指针所指向的变量或函数,需要使用一元
*
运算符。 C 语言规定,一元*
运算符的操作数必须是一个指针(即指针类型的变量或值), 如果此指针指向某变量,则一元*
运算符的结果是个左值(你可以认为左值就是代表变量的表达式 ),代表指向的变量。如果两个指针指向的类型不同,则它们是不同的指针类型。
【end】
C语言指针入门 《C语言非常道》相关推荐
- C语言 指针数组 - C语言零基础入门教程
目录 一.简介 1.数组 2.指针 3.指针和数组区别 二.指针数组 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.简介 1.数组 ...
- C语言 指针 p++ / p-- - C语言零基础入门教程
目录 一.变量 i++/i– 二.指针 p++/p– 1.通过下标访问数组元素 2.通过指针偏移访问数组元素 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> ...
- c语言指针大全,C语言指针
本篇文章帮大家学习c语言指针,包含了C语言指针使用方法.操作技巧.实例演示和注意事项,有一定的学习价值,大家可以用来参考. C语言中的指针是变量,也称为定位符或指示符,指向值的地址. 注意:指针是C语 ...
- 单片机 switch c语言,单片机入门-C51语言switch-case语句电路应用实例
原标题:单片机入门-C51语言switch-case语句电路应用实例 教学视频如下: 本例介绍switch-case选择语句的应用,用按钮控制LED灯作为实例,介绍如何使用该语句做设计.绘制了相应的电 ...
- 求最大值最小值c语言指针,用C语言指针如何求最大值最小值
问题描述:用C语言指针如何求最大值最小值 以下使一个简单的例子,用来说明指向函数的指针变量.定义两个函数max和min,分别用来求最大值和最小值.在主函数中根据用户输入的数字是1或者是2,使指针变量指 ...
- c语言指针课件,C语言指针-课件.ppt
<C语言指针-课件.ppt>由会员分享,可在线阅读,更多相关<C语言指针-课件.ppt(73页珍藏版)>请在人人文库网上搜索. 1.2020年8月13日,中国科技大学信息学院, ...
- c语言指针p1p2,C语言指针系列(2):你真的理解指针与内存的关系吗?
C语言指针可谓是C语言的灵魂,无论是在C语言算法,还是在数据结构,他无处不在.指针,这对于老手如同家常便饭一样的操作,却在萌新面前如同一座万丈高山! 中国的伟人曾经说过: 世上无难事,只怕有心人! C ...
- C语言 指针 规范,C语言学习知识指针习题集附规范标准答案.doc
C语言学习知识指针习题集附规范标准答案.doc /*一.选择题1. 变量的指针,其含义是指该变量的_________. a值 b地址 c名 d一个标志2若有语句int *point,a4;和point ...
- c语言指针概述,C语言指针概述.doc
首先,我们来看一看指针有什么用? 讲道理的话,如果你到目前没有发现指针有什么用,那就不用,挺好的. 你看C++程序员做个软件也基本不会把C++的语言特性都用上是吧.你有数组,有结构体,有函数,什么事情 ...
最新文章
- SharePoint 工作流解决方案(一):顺序工作流和状态机工作流
- 【CNN结构设计】无痛的涨点技巧:ACNet
- POJ 2455Secret Milking Machine(二分+网络流之最大流)
- pat1011-1020
- 数据埋点太难!知乎的做法有何可借鉴之处?
- 普林斯顿大学英伟达Facebook提出基于深度神经网络的全动态推理,助力轻量级网络!...
- 开源中国android代码是什么,开源中国 OsChina Android 客户端源码分析(1)启动界面 app_start...
- sql语句用变量替换表名_使用内存优化表替换SQL临时表和表变量
- Mac如何修复“无法卸载磁盘”错误
- dns服务期搭建使用_DNS服务器搭建
- java.net cidr接口_CIDR - xiaohuazi - 博客园
- Linux网络协议栈(一)——Socket入门(2)
- 【ArcGIS教程】(2)ArcMap中如何导入外部Excel属性数据呢?
- atomd525服务器性能,Atom D525性能几何?
- 鲁棒控制(棒棒控制原理)
- CATIA怎么约束快捷键_在catia软件上怎么设置快捷键_catia快捷键设置使用要注意哪些问题 - 驱动管家...
- 办公室计算机收不到主机打印机,图文详解电脑怎么连接办公室打印机 一招教你搞定!...
- 计算机和机械类哪个工资高,机械工程师和软件工程师哪个工资高前景好?
- matlab 收敛速度,BP网络的收敛速度和设计步骤【转】
- 【安全篇 / 反病毒】(5.6) ❀ 01. 反病毒的基本配置 ❀ FortiGate 防火墙