C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文
一:指针的概念
指针是一个特殊的变量,里面存储的数值是内存里的一个地址。学好指针,重要的是搞清楚指针的四个方面的内容:指针的类型、指针所指向的类型、指针所指向的内存区、指针本身占据的内存区。
1、 如何判断指针的类型呢:
int *p;
char *p;
int **p;
int (*p)[3];
int *(*p)[4];
上面的五个声明,指针的类型分别是:int *、char *、int ** 、 int (*)[3]、int *(*)[4];是不是非常简单,就是把变量名去掉,剩下的就是指针的类型。
2、指针所指向的类型
int *p;
char *p;
int **p;
int (*p)[3];
int *(*p)[4];
上面五个声明,指针所指向的类型分别是:int\char \int *\int()[3]\int *()[4],找出规律了吗?就是把变量名和一个*去掉,剩下的就是指针所指向的类型。特别强调:指针的类型和指针所指向的类型是不同的概念。
3、指针所指向的内存区或者指针的值
指针的值是指针本身所存储的数值,这个值被编译器当作一个地址,而不是而不是一个一般的数值。在32位程序里,所有的类型的指针的值都是一个32位数,因为32位程序中内存地址全部都是32位字长。
指针所指向的内存区就是从指针的值所代表的内存区开始,长度为sizeof(指针所指向的类型)的一篇内存区。以后,我们说一个指针的值是XX,就代表了该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某个内存区域,相当于指针的值就是该内存区域的首地址。
指针指向谁,就把谁的地址赋给指针。
4、指针本身所占据的内存区
指针本身占据了多大的内存。用sizeof(指针的类型)测试一个就知道了。在32位平台里,指针本身占据了四个字节的长度。
二、指针的算术运算
char a[20];
int *p=a;
p++;
指针p的类型是 int * ,指针所指向的类型是int ,它被初始化位指向整形变量a,接下来指针p被加了1,编译器是这样处理的:它把指针p的值加上了sizeof(int),在32位程序里,是加上了4.由于地址是用字节做单位的,故p的地址由原来的a的地址指向了加四个字节后的高地址。
由于char类型的长度是一个字节,所以原来p是指向数组从0开始的四个字节,现在指向了从第四个字节开始的四个字节
我们可以用一个指针和一个循环来遍历一个数组:
int arr[20];
int *p=arr;
.......//此处略去整数型赋值的代码
for(i = 0; i<20 ; i++)
{
(*p)++;
P++;
}
这个例子将整数型数组各个单元的值加1,由于每次循环都将指针p,所以每次循环都能访问数组的下一个单元。
char a[20];
int *p=a;
...
...
p+=5;
在这个例子中,p被加上了5,从编译器的角度看:将指针p的值加上sizeof(int),在32位恒旭中就是加上了5*4=20.由于地址的单位十字街,故现在p指向刚开始高字节方向的20个字节。在这个例子中,没加5之前的p指向数组第0个单元开始的四个字节,加5后,p已经指向数组的合法范围之外了。虽然这种情况在应用上会出现问题,但在语法上是可以。这体现了指针的灵活性。
总结一下:一个指针,加上一个整数n后,结果是一个新的指针pnew,pnew的类型和pnew所指向的类型与pold的类型都是一样的。pnew的值比起pold的值增加了n*sizeof(p指向的类型)个字节。加是往高字节移动,减是往低字节移动。
三 运算符&和*
&是取地址运算符,*在书上叫做间接运算符。&a的运算结果是一个指针,指针的类型是a的类型加一个*。指针所指向的类型是a的类型,指针所指向的地址就是a的地址。*p的结果是p所指向的结果,类型是p的类型,占用的地址就是p所指向的地址
int a =12;
int b;
int *p;
int *ptr; p=&a//&a的结果是一个指针,指针的类型是一个int *,指针所指向的数据类型是int ,指向的地址是a的地址。 *p=24;//*p的结果,它的类型是int,它所占用的地址是p所指向的地址,显然*p就是变量a *ptr=&P;//p本身就是一个指针了,对p在取地址,那么 该指针的类型是int **,指针所知下个的类型是 int * 。指针所指向的地址就是p的地址 **ptr=34;// *ptr的结果就是ptr所指向的东西。在这里是一个指针,对这个指针在做一次*运算,。结果就是一个int 类型的变量
四 指针表达式
一个表达式的最后结果如果是一个指针,这个表达式就叫做指针表达式
int a ,b ;
int array[10];
int *pa; pa=&a;//指针表达式
int **ptr = &pa;//表达式
*ptr=&b;//表达式
pa=array;
pa++;//表达式 char arr[20];
char **parr =arr//如果把arr看作指针的话,arr也是指针表达式
char *str; str=*parr;//指针表达式
str=*(parr+1);//指针表达式
由于指针表达式的结果是一个指针,所以指针表达式也需要具有指针的四个要素:指针的类型,指针所指向的类型、指针指向的内存区、指针自身占据的内存区。
指针在左边表示赋值,指针在右边表示取值。