文档章节

C Primer Plus 第9章 函数 9.7 指针简介

idreamo
 idreamo
发布于 2016/07/15 07:05
字数 2046
阅读 59
收藏 1

精选30+云产品,助力企业轻松上云!>>>

一般来讲,指针是一个其数值为地址的变量(或更一般地说是一个数据对象)。
正如char类型的变量用字符作为其数值,而int类型变量的数值是整数,指针变量的数值表示的是地址。
如果您将某个指针变量命名为ptr,就可以使用如下语句:
ptr=&pooh;    /*把pooh的地址赋给ptr*/
对于这个语句,我们称ptr指向poohptr和&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中的数值。

总之,普通的变量把它的数值作为基本数值量,而通过使用运算符&将它的地址作为间接数值量。但是对于指针 来讲,地址是它的基本数值量,使用运算符*后,该地址中存储的数值是它的间接数值量。

 

idreamo
粉丝 18
博文 139
码字总数 224743
作品 0
青岛
产品经理
私信 提问
加载中
请先登录后再评论。
C Primer Plus第6版_源代码+练习答案

下载地址:网盘下载 C Primer Plus(第6版)中文版详细讲解了C语言的基本概念和编程技巧。《C Primer Plus(第6版)中文版》共17章。第1、2章介绍了C语言编程的预备知识。第3~15章详细讲解了...

osc_d9817zy2
2018/07/06
14
0
C++大学教程(第九版)pdf

下载地址:网盘下载 目录 · · · · · · 第1章 计算机和C 简介 1.1简介 1.2计算机和互联网在工业和研究领域中的应用 1.3硬件和软件 1.4数据的层次结构 1.5机器语言、 汇编语言和高级语言...

osc_xyoic19y
2018/02/09
5
0
9本新书,经典升级,值得在3月里读读

图源 Pexels 经常有程序员会有这样的疑问:“看什么书能快速进阶?”事实上,能力进阶和学习同步进行的,保持学习就是在保持进步。 本月,异步社区上新了9本新书,有编程语言的入门书,也有帮...

人邮异步社区
03/31
0
0
你有一份新的C++书单,请注意查收!

C是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C擅长面向对象程序设计的同...

程序员书单
06/22
0
0
你有一份新的C++书单,请注意查收!

C是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C擅长面向对象程序设计的同...

osc_djoqamxp
06/23
4
0

没有更多内容

加载失败,请刷新页面

加载更多

VS code 可以做什么?

编写 markdown VS code 真的是非常好用的Markdown编写工具,我用他来编写Markdown的时间甚至比写代码还要多。比如,我每周写的公众号文章。 相关插件: Markdown Markdown Preview Enhanced...

osc_08vvd847
6分钟前
0
0
OC项目转Swift指南

运行环境:Xcode 11.1 Swift5.0 最近参与的一个项目需要从Objective-C(以下简称OC)转到Swift,期间遇到了一些坑,于是有了这篇总结性的文档。 如果你也有将OC项目Swift化的需求,可以作为参...

osc_p6dyctjv
6分钟前
0
0
A Bug's Life POJ - 2492

A Bug's Life Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only inte......

osc_gccs85s0
7分钟前
0
0
Go语言编程 — 项目规范

目录 文章目录 目录 项目布局(Project Layout)规范 程序核心代码目录 /cmd(Command) /pkg(Package) /internal /vendor 常规目录 /configs /init /scripts /build /deployments /test ...

osc_hdksnrrg
7分钟前
11
0
通过Windows Visual Studio远程调试WSL2中的.NET Core Linux应用程序

最近两天在Linux中调试.NET Core应用程序,同时我发现在Linux中调试.NET Core应用程序并不容易。一直习惯在Visual Studio中进行编码和调试。现在我想的是可以简单快速的测试.NET Core应用在L...

osc_jklrr90y
8分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部