指针变量就是地址,指针变量所指向的值才是具体的值。
C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式,不能通过执行调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。
1、指针变量作为函数参数:
#include <stdio.h>
void test(int x,int y)
{
int tmp;
tmp=x;
x=y;
y=tmp;
}
int main()
{
int a=10;
int b=15;
test(a,b);
printf("a=%d,b=%d\n",a,b);
return 0;
}
输出为10,15,上面这种方法不会改变a、b的值,但是用指针的写法可以改变:
#include <stdio.h>
void test(int *x,int *y)
{
int tmp;//若改为int *tmp
tmp = *x;//tmp=x;
*x = *y;//x=y;
*y = tmp;//y=tmp;在形参中交换地址,是不会改变实参中的值的,只能是前面的写法,通过改变指针变量所指向的值,来改变实参的值。
//地址没有改变,只是地址指向的值改变了。
}
int main()
{
int a = 10;
int b = 15;
test(&a,&b);
printf("a=%d,b=%d\n",a,b);
return 0;
}
输出为:15,10
2、通过指针引用数组:
2.1通过指针引用数组元素
(1)、用指针变量指向数组元素
#include<stdio.h>
int main()
{
int a[10];
int *p,i;
printf("please enter 10 integer numbers:");
for(i=0; i<10; i++)//该行可用for(p=a; p<(a+10); p++)代替
scanf("%d",&a[i]);//该行也可用scanf("%d",p);
for(p=a; p<(a+10); p++)
printf("%d ",*p);
printf("\n");
return 0;
}
(2)下标法
#include<stdio.h>
int main()
{
int a[10];
int i;
printf("please enter 10 integer numbers:");
for(i = 0; i< 10; i++)
scanf("%d" ,&a[i]);
for(i = 0; i<10; i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
(2)方法执行效率低。找数组元素费时较多。(1)方法用指针变量直接指向元素,不必每次都重新计算地址,像p++这样的自加操作是比较快的。
(3) 指向数组的指针变量也可带下标,如p[i]。带下表的指针变量的含义是:等指针变量指向数组元素时,指针变量可以带下标。因为在程序编译时,对下标的处理方法式转换为地址的,对p[i]处理成*(p+i),如果p是指向一个整形数组元素a[0],则p[i]代表a[i]。但是必须清楚p的当前值是什么。若p指向a[3],则p[2]代表a[5].
(4)**当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组名代表的是数组首元素地址,因此传递的值是地址,所以要求形参位指针变量。数组名也是相当于一个指针。**形参和实参都用数组名;形参和实参都用指针变量;或者一个用指针变量一个用数组名;这三种情况是一样的。
(5)int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};
表示形式 | 含义 含义 |
---|---|
a | 二维数组名,指向一维数组a[0],即0行首地址 |
a[0], * (a+0), * a | 0行0列元素地址 |
a+1,&a[1] | 1行首地址 |
a[1], *(a+1) | 1行0列元素a[1][0]的地址 |
a[1]+2, * (a+1)+2, &a[1][2] | 1行2列元素a[1][2]的地址 |
*(a[1]+2), ((a+1)+2), a[1][2] | 1行2列元素a[1][2]的值 |
3、指针指向函数:
**函数原型声明和定义中, 函数名前加 * 的表示返回值是指针。例如标准库函数gets():
char *gets ( char str );
从键盘读入一行字符串,如果读入成功,返回值与str 里 的 字符串相同。
int (p)(); 这种声明是“定义 p 是一个指向函数的指针变量,此函数带回整型的返回值。