懂得C 语言的人都知道,C 语言之所以强大且具有自由性,主要体现在对指针的灵活运用上。因此,说指针是C 语言的灵魂一点都不为过。既然指针如此重要,那么指针究竟是什么呢?在回答这个问题之前,我们先通过下面一段代码来看看指针的使用。
#include <stdio.h>
int main()
{
int a=2;
int *pa;
char b='t';
char *pb;
pa=&a;
pb=&b;
printf("整型指针pa占用内存大小为:%d字节\n",sizeof(pa));
printf("字符指针pb占用内存大小为:%d字节\n",sizeof(pb));
printf("整型变量a的地址为:\t%d\n",&a);
printf("字符变量b的地址为:\t%d\n",&b);
printf("整型指针pa的值:\t%d\n",pa);
printf("字符指针pb的值:\t%d\n",pb);
printf("整型指针pa+1的值:\t%d\n",pa+1);
printf("字符指针pb+1的值:\t%d\n",pb+1);
return(0);
}
fengpeng@ubuntu:~/workspace/work1$ ./test
整型指针pa占用内存大小为:4字节
字符指针pb占用内存大小为:4字节
整型变量a的地址为: 1245056
字符变量b的地址为: 1245055
整型指针pa的值: 1245056
字符指针pb的值: 1245055
整型指针pa+1的值: 1245060
字符指针pb+1的值: 1245056
现在逐一分析上面的运行结果,为什么指针变量的大小都是4 字节呢?这是因为我们使用的是32 位的计算机(ubuntu32位),内存地址都是32 位的整数,而指针变量的实质就是内存地址。
再看看整型指针变量pa 和字符型指针变量pb,它们分别用于存放整型变量a 和字符型变量b 的地址,在之后使用printf 打印语句打印出来的结果中也可以看出,pa 和pb 中存放的分别是整型变量a 和字符型变量b 的地址。
那么,什么是指针变量呢?存放地址的变量称为指针变量。指针变量是一种特殊的变量,它不同于一般的变量,一般变量存放的是数据本身,而指针变量存放的是地址。
再看两种类型的指针的运算结果,对比运算前后的结果发现,两种类型指针加1 后的变化值并不相同,如果按照一般的加法来理解,加1 以后它们的值都应该增加1,为什么整型指针的值增加的是4,而字符型指针增加的是1 呢?
下面用图来展示不同类型的变量在内存中是如何分配存储区域的。在图中,字符变量在内存中占用一个字节的大小,而整型变量在内存中占用4 个字节的大小,但是我们发现,指针变量pa 指向变量a 的地址时取的是存储变量a 在内存中的最小存储地址,而所指向的却是占用4 个字节大小的内存区域,所以从这里可以看出,我们不能简简单单地将指针理解为地址,而应该把指针理解为指向一块内存区域的起始地址,指向区域的大小视所指变量的类型而定。而指针变量与一般变量的区别就在于,指针变量存放的是地址,看看下面一段代码。
#include <stdio.h>
void main(int argc,char *argv[])
{
int a[10];
printf("a的值为:\t%d\n",a);
printf("&a的值为:\t%d\n\n",&a);
printf("a+1的值为:\t%d\n",a+1);
printf("&a+1的值为:\t%d\n",&a+1);
return ;
}
fengpeng@ubuntu:~/workspace/work1$ ./test
a的值为: 1245020
&a的值为: 1245020
a+1的值为: 1245024
&a+1的值为: 1245060
很多读者看了上面的运行结果会觉得不可思议,a 和&a 都表示数组a 的起始地址,打印出来的结果相同是显而易见的,为什么a+1 和& a+1 打印出来的结果却相差如此之大呢?回想前面讲述的内容,出现这种情况的原因是它们是不同类型的指针变量。代码中的a 其实相当于一个整型指针变量,所以它加1 的结果就和之前的分析一样,那么&a 又意味着什么呢?别急,我们先把“int a[10];”变形为“int *(&a)[10];”,这样就可以很直观地看出来,&a 就相当于指向一个int [10] 类型的指针变量,于是上面的运行结果就很容易理解了,a 到a+1 的变化就是它指向的变量所占用的内存单元的大小4 字节,而&a 到&a+1 的变化就是它指向的变量所占用的内存单元的大小4×10 字节=40 字节。
总之记住一句话:
数组名本身就是一个指针,再加上&,就变成了双指针,这里的双指针就是指二维数组,加1,就是数组整体加1行,这里就是10个元素,40个字节。
总结:
指针变量,本质上是一个变量,只是它是存放地址的变量,指针的类型代表的是它所指向的变量的类型。因此就有了指向整型、字符型、浮点型等其它类型的指针,但实际上所有类型的指针变量存放的都是int型(对于16位编译系统,比如TC,int是2字节,对于32位编译系统,比如VC,GCC,int是4字节)的地址。因此从本质上不同类型的指针变量并没有区别(因为指针变量的类型为int型,因此指针变量只能存放地址。注意和指针指向对象的类型区分开),指针变量所存储的地址为指针所指向的对象的首地址。
不同类型的指针变量之间的区别
我们都知道不同类型的指针变量指向不同类型的对象,这些指针变量结合指针运算符(*)就等价于指向的对象的值,但我们又知道所有的指针变量的类型都是一样的(都是int型)。到底声明不同类型的指针变量的背后是什么?其实声明不同类型的指针变量既是规定了该变量结合指针运算符时读取内存中的字节数,同样在指针移动和指针的运算时(加、减)在内存中移动的最小字节数。上面的例子中也已经看见了指针变量的类型确定了内存中的初始位子以及步长。(这里在强制类型转换中要加强理解)可以具体见文章http://blog.csdn.net/jinlei2009/article/details/5719325