————运算符 & * ,两者进行的是互逆过程。
进行: int a=1;int *p; p=&a;
则有: *p==a
p叫做指针变量,在c语言中,数据是储存在内存中的,p里面储存的是变量a的地址。地址是一个特殊的值,它既包括大小,也包括指针所指变量数据的类型,也就是说在不同编译器环境下,地址不一定是一个整数。
————变量的值是内存的地址
普通变量的值是实际的值,而指针变量的值是具有实际值变量的地址。
如果要看某个变量的地址,可以采取:printf("%p",&a) 或者printf("%p", p);,使用后一种办法的前提是明确指出p指向那个变量。
————指针作为函数参数
将指针传递到函数中,可以实现在函数内部访问外面的变量的能力。例如
#include<stdio.h>
int main()
{
void swap(int *a, int *b);
int x, y;
x = 2014;
y = 2021;
swap(&x, &y); //使用含指针函数的格式(把地址传进去。)
printf("%d,%d",x, y); //实现了在函数内部,改变函数外部的值。
return 0;
}
void swap(int *a, int *b) //定义含指针函数的格式。
{
int t;
t = *a;
*a = *b;
*b = t;
}
通过swap函数,交换了数值。
————数组名作为函数参数以及数组和指针的关系
int a[10];
其中, 认为 &a ==a==&a[0] ,都表示数组首元素地址
&a[0]和&a[1],之间,相差四个字节——因为数组为每一个单元分配四个字节,从上到下依次相差4。
事实上,存在这么一个等价关系,即 在函数传递中:
saga(int a[])==saga(int *a)
即 在函数值传递过程中,运算符[].进行的过程是 : a[]==*a
不是传递过程,例如 a[5]==*(a+5) a[0]==*a
数组变量本身表达地址,因此在利用过程中不需要再取地址,但数组变量的某个单元,表示的是变量,它可以进行取地址的操作。(数组的几种形式,在不同的位置具有不同的意义,要分清数组的局部和整体。)
————指针的应用
应用1:如上述swap函数,在函数内部交换两个变量的值。
应用2:函数返回多个值,某些值就只能通过指针返回。传入的参数实际上是需要保存带回的结果的变量,距离:
上述函数要返回多个值(min和max),只通过return显然是不行的。因此需要把定义出的变量min和max的地址传入函数,在函数内部访问这些变量。
应用3:函数返回运算的状态,结果通过指针返回。
return ret; //返回了运算的成果与否(运算的状态)
运算的结果通过指针返回。
可以设计“一个萝卜一个坑”,即量身定制的if条件,来使得函数返回值可以控制语句的进行,例如
if(divide(a,b,&c)), 用函数返回的值是1或者0来控制语句。
————const和指针
const修饰指针,有两种类型。
A,const修饰指针变量,即指针变量p只能用来指向固定的变量
B,const修饰 *p,即不能通过指针变量来改变变量
——区分AB两种过程
即,看const是在*的前头,还是后头。
如果:const int *p; 或者 int const *p;,他表示的都是B过程。
如果:int * const p; 表示的是A过程。//同时,在赋给p地址时,只能在定义处,也就是说只能初始化指针变量,不能在后续语句中更改。
——const修饰指针的目的
————数组和const
数组在定义的时候,就天然满足A情况,即每个指针变量所指向的都是固定的变量(某个数组单元),它是无法改变指向的。
如果再对数组进行const,就会使得数组内的每个单元都是const的(即const修饰变量,使得变量变成常变量,无法再复制。),只能通过初始化来给数组赋值。
——const数组的目的
可以保护数组中的值不被函数改变。