指针的定义
1.指针是C语言的灵魂,学不会指针就代表没有学会C语言。指针可以初略的理解为地址,一个变量的地址就称为该变量的指针,如果一个变量专门用来存放另一个变量的地址,就称该变量为指针变量。
2.指针变量的定义
常用形式为:int *point;
其中int是在定义指针时必须指定的“基本类型”,他代表的是指针变量指向的变量的类型;“*”号表示该变量的类型为指针形的变量,指针变量名是point而不是*point。指针变量只能存放地址,不能存放整形数值。如:
* point = 100;// 是错误的。因为point是个指针变量,不可以把整形数值赋值给它。
3.指针变量的引用
常用一下3种情况
(1)给指针变量赋值。如:
p = &a;
表示指针变量p的值是a的地址。
(2)引用指针变量指向的变量
如果已经执行了
p = &a;即指针p指向了a,则
printf(“%d”,*p);
其作用是输出p指向的变量的值,即a变量的值。
(3)引用指针变量的值。如
printf(“%o”,p);
其作用是以八进制的形式输出变量p的值,如果p指向a,就是输出a的地址。
(4)需要熟练掌握的几个运算符
&:取地址运算符,&a就表示a的地址。
*:取值运算符,*p就代表指针变量p指向的对象。
小练习:
/*
输入a和b两个整数,按照先大后小的顺序输出a和b
*/
#include<stdio.h>
#include<string.h>
int main()
{
int *p1,*p2,*p,a,b;
printf("请输入两个整数");
scanf("%d%d",&a,&b);
p1 = &a;
p2 = &b;
if(a<b)
{
p = p1;
p1=p2;
p2=p;
printf("a =%d,b = %d\n",a,b);
printf("max =%d,min = %d\n",*p1,*p2);
return 0;
}
运行结果如下:
从上面的程序可以看出a和b的值并未交换,但是p1和p2的值改变了。
指针变量作为函数参数
/*
输入a和b两个整数,按照先大后小的顺序输出a和b. //要求用函数实现,且用指针类型的数据作为函数参数。
*/
#include<stdio.h>
#include<string.h>
int main()
{
void swamp(int *p1,*p2);
int *point_1,*point_2,a,b;
printf("请输入两个整数");
scanf("%d%d",&a,&b);
point_1 = &a;
point_2 = &b;
if(a<b)
{
swamp(point_1,point_2);
printf("max =%d,min = %d\n",*p1,*p2);
return 0;
}
return 0;
}
void swamp(int *p1,*p2){
int temp;
temp = *p1;
*p1=*p2;
*p2= temp;
}
这个程序的功能和上一个一样,但是运用了函数和指针作为参数。
通过指针引用数组
引用数组元素可以用下标法a[2];也可以使用指针法。使用指针发目标程序高内存占用少,运行速度快。
在C语言中数组名(不包括形参数组名,形参数组并不占据实际内存单元)代表数组中的首元素地址。因此下面两句等价:
p = &a[0];
p = a;
这两个语句等价。
2.引用数组元素时指针的运算
在指针指向数组元素时,可以对指针进行一下运算:
加一个整数,如p+1:是p指向数组中的下一个元素
见一个整数,如p-1:使p指向数组中的上一个元素
自加运算,p++
自减运算,p--
两个指针相减,如p1-p2(只有p1和p2都指向同一个数组中的元素时才有意义),代表数组中两个元素之间的距离。
p1+p2是没有实际意义的。
3.通过指针引用数组元素
(1)下标法,如a[1]等形式。
(2)指针发,如*(a+1)或者*(p+1),其中a是数组名,p指向数组a。
示例:
#include<stdio.h>
#include<sttring.h>
int main()
{
int i;
int a[10];
printf("请输入十个数");
for(i = 0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(i = 0;i<10;i++)
{
printf("%d",*a[a+i]);
}
return 0;
)
运行结果如下:
4.使用中的一些注意事项
(1)p++;
*p;
作用是先使p指向下一个元素,然后取值。
(2)*p++;
由于++和*优先级同级,结合方向为自右向左,因此等价于*(p++)。
(3)*(p++)与*(++p)
他们两个的作用是不相同的,前者先去*p然后使p加1,后者先使p+1在取*p。
(4)++(*p)
表示p所指向的元素值加1.
(5)如果p指向a数组中的第i个元素,则
*(p--)相当于a[i--],先对p进行*运算,再使p自减。
*(p++)相当于a[i++],先对p进行*运算,再使p自增。
*(--p)相当于a[--i],先对p自减,再使p进行*运算。
5.使用数组名作为函数参数
一般形式为:
int main()
{
void fun(int arr[]);
int array[10];
fun(array);
return 0;
}
void fun(int arr[])
{
}
array是实参数组名,,arr为形参数组名,,此时如果形参中的元素发生变化,实参数组随着变化。因此常用这种方法通过调用一个函数改变实参数组的值。
下面通过一个表把用变量名作为函数参数和利用数组名作为函数参数做一个比较:
需要说明的是:C语言调用函数时虚实结合的方法都是采用值传递的方法,当用变量作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组代表的是地址,因此传递的值是地址,所以要求形参为指针变量。
6.通过指针引用多位数组
指针变量可以指向一维数组中的元素,也可以指向二维数组中的元素。为了说清指向多维数组的指针,我们引入二位数组的定义:
int a[2][3] = {{1,2,5},{3,4,6}};
a是二维数组名,a数组包含两行,即两个行元素,a[0],a[1],而每一个行元素又是一个一维数组。所以a[0]代表一个一维数组,,包含三个元素:a[0][0],
a[0][1],a[0][2]. 如图所示:
a[0],a[1]既然代表数组名,C语言规定数组名代表了首地址,因此a[0]代表了数组a[0]中第0列的元素的地址,即&a[0][0]。