您的位置:首页 > 编程语言 > C语言/C++

黑马程序员——C语言------指针和指针变量

2015-03-19 16:42 106 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

指针和指针变量
一、指针的概述

指针是C语言中最重要的部分,不掌握指针等于说没学过C语言。在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等。为了正确地访问这些内存单元,必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。内存单元的指针和内存单元的内容是两个不同的概念。在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。

一个指针是一个地址,是一个常量。而一个指针变量却可以被赋予不同的指针值,是变量。但常把指针变量简称为指针。为了避免混淆,我们中约定:“指针”是指地址,是常量,“指针变量”是指取值为地址的变量。定义指针的目的是为了通过指针去访问内存单元。既然指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其它数据结构的地址。在一个指针变量中存放一个数组或一个函数的首地址有何意义呢?因为数组或函数都是连续存放的。通过访问指针变量取得了数组或函数的首地址,也就找到了该数组或函数。这样一来,凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指针变量中赋予数组或函数的首地址即可。在C语言中,一种数据类型或数据结构往往都占有一组连续的内存单元。用“地址”这个概念并不能很好地描述一种数据类型或数据结构,而“指针”虽然实际上也是一个地址,但它却是一个数据结构的首地址,它是“指向”一个数据结构的。

二、变量的指针和指针变量

变量的指针就是变量的地址。存放变量地址的变量是指针变量。即在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个变量的地址或称为某变量的指针。为了表示指针变量和它所指向的变量之间的关系,在程序中用“*”符号表示“指向”,例如,pointer代表指针变量,而*pointer是pointer所指向的变量。

定义一个指针变量的一般形式:

类型说明符 *变量名

*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。

例如:

int *p;

表示p是一个指针变量,它的值是某个整型变量的地址,即p指向一个整型变量。

注意:

1.一个指针变量只能指向同类型的变量

2.指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用,否则将造成系统混乱,甚至死机。

3.指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误。

有关的运算符:

1.取地址运算符:&

其一般形式为:&变量名,例如&a,取a的地址。

2.指针运算符(或称“间接访问”运算符):*

注意:两种运算符都是从右至左结合。指针运算符*和指针变量说明中的指针说明符*不是一回事。在指针变量说明中,“*”是类型说明符,表示其后的变量是指针类型。而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。

三、初始化方法

1.先定义后初始化

// 定义int类型的变量a

int a = 10;

// 定义一个指针变量p

int *p;

// 将变量a的地址赋值给指针变量p,所以指针变量p指向变量a

p = &a;

2.在定义的同时初始化

// 定义int类型的变量a

int a = 10;

// 定义一个指针变量p

// 并将变量a的地址赋值给指针变量p,所以指针变量p指向变量a

int *p =&a;

通过指针访问它所指向的一个变量是以间接访问的形式进行的,所以比直接访问一个变量要费时间,而且不直观,因为通过指针要访问哪一个变量,取决于指针的值(即指向),但由于指针是变量,我们可以通过改变它们的指向,以间接访问不同的变量这给程序员带来灵活性,也使程序代码编写得更为简洁和有效。

两指针变量相减:两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数。实际上是两个指针值(地址)相减之差再除以该数组元素的长度(字节数)。两个指针变量不能进行加法运算。

两指针变量进行关系运算:指向同一数组的两指针变量进行关系运算可表示它们所指数组元素之间的关系。

例如:

p1==p2 表示p1和p2指向同一数组元素

p1>p2 表示p1处于高地址位置

p1<p2 表示p2处于低地址位置

p==0 表示p是空指针,它不指向任何变量,空指针是由对指针变量赋予0值而得到的。

p!=0 表示p不是空指针。

指针变量未赋值时,可以是任意值,是不能使用的,否则将造成意外错误,而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已。

指针变量可以加减运算或者+ + 、- -,+n,如指针变量加1,即向后移动1 个位置表示指针变量指向下一个数据元素的首地址。

四、指针应用实例

1.写一个函数swap交换两个实参的值。

1> 如果不用指针

void swap(char d1, char d2)
{
printf("交换前:d1=%d, d2=%d\n", d1, d2);

// 定义一个中间变量
char temp;

// 交换d1和d2的值
temp = d1;
d1 = d2;
d2 = temp;

printf("交换后:d1=%d, d2=%d\n", d1, d2);
}

int main()
{
char a = 10, b= 9;
printf("交换前:a=%d, b=%d\n", a, b);

swap(a, b);

printf("交换后:a=%d, b=%d", a, b);
return 0;
}


虽然d1和d2的值被交换了,但是变量a和b的值根本就没有换过来。因为基本数据类型作为函数实参时,只是纯粹地将值传递给形参,形参的改变并不影响实参。

2> 但我们使用指针,问题就会迎刃而解

void swap(int *d1, int *d2)
{
// 中间变量
char temp;

// 取出d1指向的变量的值
temp = *d1;

// 取出d2指向的变量的值,然后赋值给d1指向的变量
*d1 = *d2;

// 赋值给d2指向的变量
*d2 = temp;
}
int main()
{
char a = 10, b= 9;
printf("交换前:a=%d, b=%d\n", a, b);

swap(&a,&b);

printf("交换后:a=%d, b=%d", a, b);
return 0;
}


这样通过指针就能在一个函数的内部改变外部的实参。

还有就是要注意指针变量要分类型,不然读取数据会发生错误,因为类型不同,占用内存不同。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: