◆指针可以称得上是C语言的灵魂,正因为有了指针这一强大的功能,让C语言操作的灵活度能够达到一个更高的层次,同时使得C语言在各类编程语言中拥有不可取缔的地位。初学时感到C语言中的指针的相关知识点很繁琐,也很绕,进而许多概念极易混淆,特此整理指针的初级相关知识点。



1. ★指针的概念

地址与指针?

地址:C程序中的变量在占有一个可标识的存储区,每一个存储区是由若干字节组成,而每一个字节都有自己的地址,而一个存储区的地址则为该存储区第一个字节的地址。(&

存储区访问:存储区的访问方式有直接访问和间接访问两种,直接访问顾名思义就是通过变量名或地址访问变量的存储区,间接访问则为一个变量的地址存放在另一个变量中。如:将X的地址放到P中,访问X时先找到P,再由P中存放的地址找到X

指针:一个变量的指针则为该变量的地址(指针在某种程度上就是地址),而指针变量就是存放变量地址的变量,用来指向另一个变量。





2. ★指针变量的引用:

指针运算符(*

例:p*pp*p不同,p是指针变量,p的值是p所指向的变量的地址。*pp所指向的变量,*p的值是p所指向的变量的值。

C函数调用是按值传递的,传入参数在子函数中只是一个初值相等的副本,无法对传入参数作任何改动。但实际编程中,经常要改动传入参数的值。这一点我们可以用传入参数的地址而不是原参数本身,当对传入参数(地址)取(*)运算时,就可以直接在内存中修改,从而改动原想作为传入参数的参数值如下该例:

#include<stdio.h>
void fun(int *val)
{
(*val)++;
}
Int main()
{
Int a=3;
fun(&a);
printf(“%d”,a);
return 0;
}

注:在执行inc(&a);时,系统在内存分配表里增加了一行fun中的val”,其地址为新地址,值为&a。操作*val,即是在操作了。



3. *&运算

 *运算:(*p)操作是这样一种运算,返回的值作为地址的那个空间的取值。&运算:(&p)则是这样一种运算,返回当时声明时开辟的地址。显然可以用赋值语句对内存地址赋值。

※注:两个地方要注意在程序声明变量的时候的*,只是表明它是一个无符号整数,这个整数指向某个内存地址,一次访问sizeof(type)长度这点不要和(*)操作符混淆;在C++程序声明变量的时候的&,只是表明它是一个引用,这个引用声明时不开辟新空间,它在内存分配表加入新的一行,该行内存地址等于和调用时传入的对应参数内存地址,与(&)操作符不同。



4. ★指针的初始化

对指针进行初始化或赋值只能使用以下四种类型的值:

.0值常量表达式,例如,在编译时可获得0值的整型 const对象或字面值常量0

.类型匹配的对象的地址

.另一对象末的下一地址

.同类型的另一个有效指针。

注:int型变量赋给指针是非法的,尽管此int型变量的值可能0。但允许把数值0或在编译时可获得0值的const量赋给指针



5. ★指针数组,数组指针,函数指针

①指针数组:就是一个由指针组成的数组,那个数组的各个元素都是指针,指向某个内存地址char *p[10]p是一个指针数组。指针数组的运用可以作为函数的参量使用,使用方式与普通数组类似。并且指针数组常适用于指向若干字符串,这样使字符串处理更加灵活方便

②数组指针:数组名本身就是一个指针,指向数组的首地址。注意这是一个常数。char (*p)[10]中p是一个数组指针其本质为指针(这个指针存放的是数组首地址的地址,相当于2级指针,这个指针不可移动)。例如:

{
int a[4][5];
int (*p)[5]=a;
}

※注:这里a是个二维数组的数组名,相当于一个二级指针常量p是一个指针变量,它指向包含5int元素的一维数组,此时p的增量以它所指向的一维数组长度为单位;*p+i是二维数组a[0][i]的地址*(p+2)+3表示a[2][3]地址(第一行为0行,第一列为0列),**(p+2)+3)表示a[2][3]的值。

※对于二维数组来说:二维数组:char str[10][10]只要定义了一个二维数组,无论赋不赋值,系统都会给他分配相应空间,而且该空间一定是连续的。其每个元素表示一个字符。我们可以通过指定下标对其元素进行修改。而指针数组:char *str[5]系统至少会分配5个连续的空间用来存储5个元素,表示str是一个5个元素的数组,每个元素是一个指向字符型的一个指针。

总结:相比于比二维字符数组,指针数组有明显的优点一是指针数组中每个元素所指的字符串不必限制在相同的字符长度;二是访问指针数组中的一个元素是用指针间接进行的,效率比下标方式要高。 但是二维字符数组却可以通过下标很方便的修改某一元素的值,而指针数组却无法这么做。

③函数指针:本身是一个指针,指向一个函数入口地址,通过该指针可调用其指向的函数,使用函数指针可实现回调函数 常见的函数体中其本身是一个函数,其返回值是一个指针的形式。



6. ★指针与引用(C++风格)

不同点:

.指针是一个实体,而引用仅是个别名

.引用使用时无需解引用(*),指针需要解引用

.引用只能在定义时被初始化一次,之后不可变;指针可变;引用从一而终

引用没const,指针有constconst的指针不可变

引用不能为空,指针可以为空

⑥引用是类型安全的,而指针不是(引用比指针多了类型检查)

“sizeof引用得到的是所指向的变量(对象)的大小,“sizeof指针得到的是指针本身(所指向的变量或对象的地址)的大小

相同点:两者都是属于地址范畴的概念,指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。