scanf_s("%d",&arr[i]);
}
void output_fun(int * arr,int n)
{
int i;
for(i=0;i
printf("%-2d",* arr);
}
//void fun(int arr[],int n)和void fun(int * arr,int n)等价。
//这里就是程序中遇到的两种方式。
指针与指针变量
一个变量的地址称为该变量的指针。
如果有一个变量是专门用来存放另一个变量的地址(即指针),则它称为指针变量。
指针变量就是地址变量,指针变量的值就是地址。
指针变量作为函数参数
主调函数的实参是指针变量,在函数调用时,将实参变量的值传递给形参变量,这里依然是单向的值传递,但是传递的内容是实参的地址。这就与数组名的传递是一样的道理。
不能通过执行调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值。
归纳:数组名与指针变量
(1)形参和实参都用数组名;
(2)实参用数组名,形参用指针变量;
(3)实参和形参都用指针变量;
(4)实参为指针变量,形参用数组名。
值得注意的是:如果用指针变量作为实参,必须先使指针变量有确定值,指向一个已定义的对象。
数组元素的指针
引用数组元素可以用下标法(如a[i]),也可以用指针法
(如*(a+i)或*(p+i))
。下面这几种写法等价,都是使指针变量p指向数组a的首地址。其中a为已定义的数组名。
(1)int * p=&a[0];
(2)int * p=a;
(3)int * p;p=a;
(4)int * p;p=&a[0];
在指针指向数组元素时,可以对指针进行以下运算:
加一个整数(+或+=);
减一个整数(-或-=);
自加运算;
自减运算;
两个指针相减,如p1-p2(只有p1和p2都指向同一数组中的元素时才有意义)。
指针就是地址,两个指针相减可知道它们所指向元素的相对距离。地址不能相加,如p1+p2是无实际意义的。
二维数组a[][]
二维数组名(如a)是指向行的。因此a+1中的“1”代表一行中全部元素所占的字节数。
一维数组名(如a[0],a[1])是指向列元素的。a[0]+1中的1代表一个a元素所占的字节数。
在指向行的指针前面加一个*,就转换为指向列的指针。如,*a和*(a+1),分别指向a数组的0行0列的元素和1行0列的元素。
在指向列的指针前面加&,就成为指向行的指针。如,a[0]指向的是0行0列元素的指针,在前面加一个&之后,由于a[0]与*(a+0)等价,因此&a[0]与&*a等价,也就是与a等价,它指向二维数组的0行。
指向多维数组的指针变量
(1)指向数组元素的指针变量
举个例子,指向二维数组元素的指针变量
#include
int main(void)
{
void input_output_array_fun(int *);
int a[3][4];
int * pointer;
pointer=a[0]; //这里使指针变量pointer指向0行0列元素地址。
input_output_array_fun(pointer);
return 0;
}
void input_output_array_fun(int * p)
{
int i;
for(i=0;i<12;i++)
scanf_s("%d",p+i);
for(i=0;i<12;i++)
{
printf("%-5d",*(p+i));
if((i+1)%4==0)printf("\n");
}//for
}
(2)指向由m个元素组成的一维数组的指针变量
如int (* p)[4],p的类型是int(*)[4],p被定义为指向一维整型数组的指针变量,一维数组有4个元素,因此p的基类型是一维数组,其长度为16字节。
#include
int main(void){
void input_output_array_fun(int (* p) [4]);
int a[3][4];
int (* pointer)[4];
pointer=a; //这里使指针变量pointer指向0行。
input_output_array_fun(pointer);
return 0;
}
void input_output_array_fun(int (* p)[4]){
int i,j;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
scanf_s("%d",*(p+i)+j);
for(i=0;i<3;i++)
for(j=0;j<4;j++)
{
printf("%-5d",*(*(p+i)+j));
if(j==3)printf("\n");
}//for(i=0;)
}
通过指针引用字符串
通过字符数组名或者字符指针变量可以输出一个字符串,而对一个数值型数组,是不能企图用数组名输出它的全部元素的,只能逐个输入。
字符数组从键盘输入的时候调用gets_s()函数;
数值型数组从键盘输入的时候调用scanf_s()函数。
字符指针变量和字符数组的比较
(1)字符指针变量中存放的是地址。字符数组由若干个元素组成,每个元素中存放一个字符。
(2)可以对字符指针变量赋值。不能对字符数组名赋值。如:
char *a;
a="I care."; //合法
char str[10];
str="I care."; //非法
str[0]="I";//合法。一旦字符数组没有在初始化时赋值,只能逐个赋值。
(3)初始化。
字符指针变量:
char *a="I care.";
等价于
char *a;
a="I care.";
字符数组:
char str[10]="I care."; //合法
不等价于
char str[10];
str[]="I care.";//不能用赋值语句对字符数组中全部元素整体赋值。
(4)字符指针变量在编译时,只分配一个存储单元(用来存放字符串的起始地址)。字符数组在编译时会分配若干存储单元,以存放各元素的值。
(5)指针变量的值是可以改变的。数组名代表一个固定的值(数组首元素的地址),不可改变。
(6)字符指针变量所指向的字符常量中的内容是不可以被取代的(不能对它们再赋值),字符数组中各元素的值是可以改变的。如:
char a[]="you.";
char *b="you.";
a[1]='a'; //合法
b[1]='a'; //非法
(7)引用数组元素时,字符数组可以用下标法引用一个数组元素(如a[2]),也可以用地址法(如*(a+2)引用数组元素a[2])。如果定义了字符指针变量p,并使它指向了数组a的首元素,则可以用指针变量带下标的形式引用数组元素(如p[5]),同样可以用地址法(如*(p+5))引用数组元素a[5]。
(8)用指针变量指向一个格式字符串,能轻松实现可变格式输出函数。如:
char *p;
p="a=%d,b=%f\n";
printf(p,a,b);
相当于
printf("a=%d,b=%f\n",a,b);
使用字符数组也能达到这一目的,但只能在定义数组时初始化或逐个对元素赋值的方法。显然指针变量指向字符串的方式更为方便。