C Primer Plus 第9章 函数 9.7 指针简介
2019独角兽企业重金招聘Python工程师标准>>>
一般来讲,指针是一个其数值为地址的变量(或更一般地说是一个数据对象)。
正如char类型的变量用字符作为其数值,而int类型变量的数值是整数,指针变量的数值表示的是地址。
如果您将某个指针变量命名为ptr,就可以使用如下语句:
ptr=&pooh; /*把pooh的地址赋给ptr*/
对于这个语句,我们称ptr指向pooh。ptr和&pooh的区别在于前者为一变量,而后者是一个常量。当然,ptr可以指向任何地方:
ptr=%bah; /*令ptr指向bah而不是pooh*/
这时,ptr的值是bah的地址。
要创建一个指针变量,首先需要声明其类型。假设您想把ptr声明为可以存放一个int数值的地址,就需要 使用下面介绍的新运算符。
9.7.1 间接运算符
假定ptr指向bah,如下所示:
ptr = &bah;
这时就可以使用间接(indirection)运算符*(也称作取值(dereferencing))来获取bah中存放的数值(不要把这种一元运算符和表示乘法的二元运算符*相混淆)。
val = *ptr; /*得到ptr指向的值*/
语句ptr=&bah;以及语句val=*ptr;放在一起等同于下面的语句:
val = bah;
由此看出,使用地址运算符和间接运算符可以间接完成上述语句的功能,这也正是“间接运算符”名称的由来。
9.7.2 指针声明
pointer ptr; /*不能这样声明一个指针*/
为什么不能这样声明?因为这对于声明一个变量为指针是不够的,还需要说明指针所指向变量的类型。原因是不同的变量类型占用的存储空间大小不同,而有些指针操作需要知道变量类型所占用的存储空间。同时,程序也需要了解地址中存储的是何种类型的数据。例如,long和float两种类型的数值可能使用相同大小的存储空间,但是它们的数据存储方式完全不同。指针的声明形式如下:
int *pi; /*pi是指向一个整数变量的指针*/
char *pc; /*pc是指向一个字符变量的指针*/
float *pf,*pg; /*pf和pg是指向浮点变量的指针*/
类型标识符表明了被指向变量的类型,而星号(*)表示该变量为一指针。声明int *pi; 的意思是pi是一个指针,而且*pi是int类型的。
*和指针之间的空格是可选的。
pc所指向的值(*pc)是char类型的。而pc本身又是什么类型呢?我们把它描述为“指向char的指针”类型。pc的值是一个地址,在大多数系统内部,它由一个无符号整数表示。但是,这并不表示可以把指针看作是整数类型。一些处理整数的方法不能用来处理指针,反之亦然。例如,可以进行两个整数相乘,而指针则不能。因此,指针的确是一种新的数据类型,而不是整数类型。所以,正如前面提到的,ANSI C 专门为指针提供了%p输出格式 。
9.7.3 使用指针在函数间通信
在程序清单9.15中,函数interchange()使用了指针参数,我们将对该函数进行详细的讨论。
程序清单9.15 swap3.c程序
#include <stdio.h>
void interchange(int *u,int *v);
int main(void)
{int x = 5,y = 10;printf("Originally x = %d and y=%d.\n",x,y);interchange(&x,&y); /*向函数传送地址*/printf("Now x = %d and y = %d.\n",x,y);return 0;
}void interchange(int *u,int *v)
{int temp;temp = *u; /*temp得到u指向的值*/*u = *v;*v = temp;
}
下面我们分析程序清单9.15的运行情况,首先,函数调用语句如下:
interchange(&x,&y);
可以看出,函数传递的是x和y的地址而不是它们的值。这就意味着interchange()函数原型声明和定义中的形式参数u和v将使用地址作为它们的值。因此,它们应该声明为指针。由于x和y都是整数,所以u和v是指向整数的指针。其声明如下:
void interchange(int *u,int *v)
接下来,函数体进行如下声明:
int temp;
从而提供了所需的临时变量。为了把x的值存储在temp中,需要使用以下语句:
temp = *u;
注意,因为u的值是&x,所以u指向x的地址。这就意味着*u代表了x的值,而这正是我们需要的数值。不要写成如下这样:
temp = u; /*这样做不行*/
上面的语句中,因为赋给变量temp的只是x的地址而不是x的值,所以不能实现数值的交换。
同样,把y的值赋给x,需要使用下面的语句:
*u = *v;
其执行结果相当于:
x = y;
在示例程序中,我们用一个函数实现了x和y的数值交换。首先,函数使用xy的地址作为参数,这使它可以访问xy变量。通过使用指针和运算符*,函数可以获得相应存储地址的数据,从而就可以改变这些数据。
通常情况下,可以把关于变量的两类信息传递给一个函数。如果函数的调用形式如下:
funcation (x);
这是传递的是x的值。但是如果使用下面这种函数调用形式:
funcation (&x);
那么会把x的地址传递给函数。第一种调用形式要求函数定义部分必须包含一个和x具有相同数据类型的形式参数。如下所示:
int function (int num);
而第二种形式要求函数定义部分的形式参数必须是指向相应数据类型的指针:
int funcation (int *ptr);
使用函数进行数据计算等操作时,可以使用第一种形式。但是,如果需要改变调用函数中的多个变量的值时,就需要使用第二种形式。其实,使用scanf()时已经使用了第二种形式。例如,当需要为变量num读取一个数值时,可以调用函数scanf("%d",&num);该函数调用的意思是先读取一个数值,然后将其存储到通过参数获得的地址中。
尽管interchange()只使用局部变量,但是通过使用指针,该 函数可以操作main()中变量的值。
***************************************************
关于变量:变量名称、地址和数值
前面关于指针的讨论中,变量名称、地址以及数值之间的关系是其关键所在。
编写程序时,一个变量一般有两种属性:变量名和数值(当然,还有其他属性,如数据类型等,但它们与这个主题无关)。程序被编译和加载后,同一个变量在计算机中的两个属性是地址和数值。变量的地址可以被看作是在计算机中变量的名称。
在许多编程语言中,变量地址只由计算机处理,对于编程人员来讲完全不可见。但是在C中,可以使用运算符&对变量的地址进行操作。
&barn就表示变量barn的地址。
可以通过使用变量名获得变量的数值。
例如printf("%d\n",barn)输出的是barn的数值。
当然 ,也可以使用运算符*从地址中获取相应的数值。
对于语句pbarn = &barn;,*pbarn是存储在地址&barn中的数值。
总之,普通的变量把它的数值作为基本数值量,而通过使用运算符&将它的地址作为间接数值量。但是对于指针 来讲,地址是它的基本数值量,使用运算符*后,该地址中存储的数值是它的间接数值量。
转载于:https://my.oschina.net/idreamo/blog/712089
C Primer Plus 第9章 函数 9.7 指针简介相关推荐
- C++学习之路(六),C++primer plus 第七章 函数--C++的编程模块
第 7 章 函数---C++的编程模块 本章内容包括: 函数基本知识. 函数原型. 按值传递函数参数. 设计处理数组的函数. 使用 const 指针参数. 设计处理文本字符串的函数. 设计处理结构的函 ...
- C Primer Plus 第9章 函数 9.4 多源代码文件程序的编译
2019独角兽企业重金招聘Python工程师标准>>> 9.4.1 UNIX 首先假定UNIX系统下安装了标准的UNIX C 编译器cc.文件file1.c和file2.c中包含有 ...
- 【C++ primer】第七章 函数-C++的编程模块
1,函数的基本知识 C++对于返回值的类型有一定的限制:不能是数组,但可以使其他任何类型,甚至可以使结构和对象. 有趣的是,虽然数组不可以作为返回对象,但是数组可以作为结构 ...
- C++ Primer 第五版 第6章——函数阅读笔记及习题答案(完整,附C++代码)
C++Primer(第五版)第6章函数的阅读笔记及课后习题答案总结,课后习题答案是自己学习写出来的,如果有误,欢迎指正 还不完整,后续会更新添加 阅读笔记 C++ Primer 第五版 第6章 6.1 ...
- 《C++ Primer》读书笔记—第六章 函数
声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程 一.函数基础 1.一个典型的函数定义包括以下内容:返回 ...
- C++ Primer 第六章—— 函数 思维导图
C++ Primer 第六章-- 函数 思维导图 前言:该博文的定位是,您已经对C语言的基础知识和C++ Primer该书或C++知识有了基本了解.而在阅读C++ Primer(第五版)之后,感觉知识 ...
- C++Primer学习笔记:第6章 函数
通过调用运算符()调用函数 函数的调用完成两项工作: 用实参初始化函数对应的形参 将控制权转移给被调用函数:主调函数的执行被暂时中断,被调函数开始执行 尽管实参与形参存在对应关系,但是并没有规定实参的 ...
- 《C Primer Plus》—第九章:函数(指针间接,函数及其定义方式,ANSI C原型,递归,函数调用的底层原理)
文章目录 函数 本章内容 复习函数 创建并使用简单函数 分析程序 函数参数 定义带形式参数的函数 声明带形式参数函数的原型 调用带实际参数的函数 使用return从函数中返回值 函数类型 ANSI C ...
- C Primer Plus 第11章_字符串和字符串函数_代码和练习题
11.1 表示字符串和字符串I/O 字符串是以空字符(\0)结尾的char类型数据. strings1.c 演示在程序中表示字符串的几种方式 #include <stdio.h> #def ...
- C++ primer第六章函数的学习
介绍 首先介绍函数的定义和声明,包括如何传入参数以及函数如何返回结果. C++语言允许使用重载函数,即几个不同的函数可以使用向同一个名字.所以接下来介绍重载函数的方法,以及编译器选择如何从函数的若干重 ...
最新文章
- 上海大学c语言程序设计,上海大学2009-C语言程序设计秋季学期试卷.doc
- .NET Core微服务之基于Ocelot实现API网关服务(续)
- 我的个人网站更新了!
- 设计微服务架构需要掌握的基础知识
- 处理数据包的开源项目FD.IO
- 硬件基础:电脑当中各个硬件的作用介绍
- 有哪些你踏入社会才明白的道理
- 《白鹿原》金句摘抄(四)
- python定时任务是异步的吗_定时任务、异步任务
- java jar包示例_Java包getSpecificationVersion()方法和示例
- Filecoin网络目前总质押量约为4018万枚FIL
- Java并发编程框架Disruptor
- java通过+拼接字符串导致的无效SQL,三目运算符与+运算符结合使用时需要注意了
- 稳扎稳打Silverlight(5) - 2.0控件之ListBox, MediaElement, MultiScaleImage, PasswordBox
- SSM框架整合环境搭建
- 低代码学习教程:如何编辑自定义打印模版?
- 利用Greenfoot制作简单的小游戏——记忆翻牌游戏(三)
- 计算机如何磁盘整理,如何整理磁盘碎片让Win7电脑运行更快?
- android学习资源大整合(持续更新ing)
- linux命令里的xz是干嘛的,xz命令 - Linux命令大全 | linux教程
热门文章
- 扩展欧几里德算法的定义、解释、证明及其应用
- 把业务逻辑变成数据结构和SQL语句的例子。自然架构改成自然框架
- 国产达梦数据库管理系统-通过Excel文件导入数据
- 很多同学工作了,这里呢简单说说工作中吧可能会遇到的一些事情‘
- Ext JS学习第八天 Ext基础之 认识Ext.js 和Ext-more.js
- HDU 1024 (不重叠m段最大和) Max Sum Plus Plus
- DELPHI XE5 FOR ANDROID 模仿驾考宝典 TMEMO 控件随着字数增多自动增高
- python_ 学习笔记(基础语法)
- 响应式微服务架构-分布式系统设计原则
- python3----练习题(图片转字符画)