1、指针是什么?
要想明白指针的含义,首先应该明白变量在内存中是如何存储的,如何读取的。内存中每个内存单元都有一个地址,这好比旅馆中每个房间,都有唯一的房间号。至于内存单元中到底存放的是什么内容,那是我们定义的变量。当我们定义一个变量时,系统会根据我们声明的数据类型而为变量分配适当的存储空间。如c语言中的int类型的变量,系统会为他分配2个字节的内存单元。而当程序经过编译以后,原来的变量已经转换为变量的地址,对变量值的存取都是通过地址进行的。在c语言中,将变量的地址形象的称为“指针”。所以说:指针就是变量的地址。
2、指针变量
指针变量与指针是两个不同的概念。指针是变量的地址,而指针变量是存储地址的变量,换句话说,指针变量就是存储指针的变量。
定义指针变量的格式是:基类型 *指针变量名;如:float *pointer1;其中,基类型是该指针所指向的目标变量的数据类型。
可以将某个已初始化的,基类型相同的指针变量赋值给指针变量。如:int i; int *p=&i;
Int *q=p;
其中,&和* 是两种运算符,&是取地址运算符,*是指针运算符。如&a是a的地址,*p是指针p所指向存储单元的内容。
3、指针变量作为函数参数(***)
首先应该明白:指针变量作为函数参数和非指针变量作为函数参数有着质的区别。因为c语言中函数参数是“单向值传递”。调用函数将实参的值传给形参,然后就不会再管形参的命运了。打个比方,我把我的文件复制了一份给了另一个人,至于他对那份复制品所做的任何修改也不会对我的源文件产生丝毫影响。但用指针变量作为形参就不同了,虽然他仍然是“值传递”,但传递的变量的地址。同样打个比方,旅馆原来的两个房间号分别是303和304,
303中住的是王先生,304中住的是张先生。现在,我说:“303的住户是王先生,304的住户是张先生”。但现在,我只将303和304的房间号对换,则我现在应该说:“303的住户是张先生,304的住户是王先生”了。下面再看两个交换函数,看看为什么一个可以成功交换,而另一个却不可以。
void swap(int x, int y)
{
int temp;
temp=x;
x=y;
y=temp;
}
在main函数中,调用swap函数,swap(a, b);结果,main函数输出的结果根本还是未交换的a,b。
void swap(int *pointerx, int *pointery)
{
int *temp;
*temp=*pointerx;
*pointerx=*pointery;
*pointery=*temp;
}
在main函数中,调用swap函数,swap(a, b);结果,main函数输出的结果是交换后的的a,b。
4、指针与数组
数组元素的指针就是数组元素的地址。C语言规定,数组名代表数组中首元素的地址。
因此,一个指向数组的指针,就是指向这个数组的首元素的地址。所以,int a[10]; int *p;
P=a与p=&a[0]是等同的。
在c语言中,如果,指针p已经指向数组的第一个元素,则p+1指向数组的下一个元素,而不是将p的值简单的加1。如:如果数组为int类型,则原来p指向2000地址,则p+1指向2002,而*(p+1)则为该数组元素的值。*(p+i)与p[i]是等价的。
若数组是2维的,如:a[10][10],则a,a[0], &a[0] &a[0][0]都可以表示该二维数组的首地址。a,a+i,a[i],*(a+i),*(a+i)+j, a[i]+j都是地址。
5、字符串与指针
可以将一个字符串赋值给一个字符型指针变量。如:char *strpointer=“I love China”;但注意,这里不是将“I love China”几个字符赋值给strpointer指针变量,而是将该字符串的首地址赋值给了strpointer。输出时用printf(“%s” strpointer);即可
6、指向函数的指针
一个函数在编译时被分配给一个入口地址,这个入口地址就是该函数的指针。所以可以用一个指针变量指向该函数。函数名称就代表该函数的入口地址。定义的格式如下:
数据类型 (*指针变量名)(函数参数列表)。如:int (*p)(int x, int y);另外,函数的返回值也可以是指针类型。
7、指针数组和指向指针的指针
一个数组,如果他的所有元素的类型都是指针,则我们就称这个数组为指针数组。定义指针数组的格式如下:类型名 *数组名[数组长度];如:int *p[4]; 就是一个包含四个指针的数组。
指针的指针,顾名思义就是指针所指向的类型依然是一个指针类型。定义格式如下:类型名 **变量名。如:int **p;
一个指针数组的数组名就是一个双重指针,可以进行自增自减运算。
一个二维数组的数组名同样可以理解为一个双重指针,可以定义一个双重指针指向某个二维数组。