小知识点(1)
- 数组作为函数参数
- 指针变量做函数参数
1.数组作为函数参数
例:(整形数组)简单的输入输出
输出为函数,主要探讨数组作为函数参数时的意义。
#include<stdio.h>
void Output(int a[]);
int main()
{
int i;
int a[5];
for(i=0;i<5;i++) //整型数组的读入
{
scanf("%d",&a[i]);
}
Output(a);
return 0;
}
void Output(int a[]) //整型数组的输出
{
int i;
for(i=0;i<5;i++)
{
printf("%d",a[i]);
}
printf("\n");
}
那实参跟形参是否一样呢?
先做一个实验。
大家知道对数组名用sizeof,求得的将会是整个数组的长度,那么对形参呢?
void Output(int a[]) //在输出函数中加入sizeof运算符;
{
int i;
for(i=0;i<5;i++)
{
printf("%d",a[i]);
}
printf("\n");
printf("sizeof(a)=%d",sizeof(a));
}
我的输出结果是sizaof(a)=8
(有的电脑可能是4)
这个例子说明,存在形参里面,即函数里面的a实际上只是一个指针变量,里面存放是的主函数中a的地址,而c中指针变量的长度是4(有的是8,跟操作系统相关)
所以,此处对int a[]
的声明也相当于int *a
;
而使用[]
的好处就是可以显示的表示该参数将被作为指向数组的指针。
(就像定义指针变量,int *p
中的*
只是为了说明p这个变量时指针类型而不是单纯的整形变量,在这里并不起解引用的作用)
而值得注意的是:
①数组在内存中是连续储存的;实参数组在向函数的形参数组传递时,需要传递的只是数组的首地址(即数组名)和长度,而在传递实参时,如果写成a[10]
系统只会检测数组名,而不会检测里面的内容([]
内的任何常量表达式都会被忽略,而被自动转化为指针类型),所以数组长度需要另外定义一个变量来传递;
既然说传递的只是数组名及长度,并且函数形参中a只是一个指针变量,为什么像下面这样的程序可以输出原数组的长度(即操作原数组),而不需要写什么*a
呢?
(改成以字符数组为例)
#include<stdio.h>
#include<string.h>
void Output(char a[]);
int main()
{
int i;
char a[5];
for(i=0;i<5;i++) //输入字符数组
{
scanf("%c",&a[i]);
}
Output(a);
return 0;
}
void Output(char arrey[]) //输出字符数组
{
int i;
int x=strlen(arrey); //使用了a这个形参(在此处是形参,即主函数中a[]数组的首地址)
for(i=0;i<5;i++)
{
printf("%c",arrey[i]);
}
printf("\n");
printf("len=%d",x);
}
原因:
strlen
跟sizeof
的通性;
strlen()
函数的原型为:unsigned int strlen (char *s);
s为指定的字符串;
strlen()
后面只需要字符数组的首地址即可。
而在函数中可以直接写arrey[5]=5
之类的语句来改变原数组的值,是因为
此处的arrey是形参变量,已经存放了原数组a的首地址,就可以当作a来使用;
(此处相当于指针的用法了,如果在原函数中定义*p=a
,再给p赋值p=a
,这以后原数组a[]
可以直接用*p
、*(p+1)
或者p[]
来代替,具体的可以参照指针跟一维数组的关系)
2.指针变量做函数参数(指针传参)
例:统计重复字符
编程并计算所输入字符串中连续重复出现次数最多的字符,输出该字符及次数
#include<stdio.h>
#include<string.h>
int CountRepeatStr(char str[], int *tag); //注意tag这个参数的用法
int main()
{
char s[81];
int count; //统计出现的次数
int tag=0; //统计次数最多的字符的下标(也可以让函数直接返回次数最多的字符)
printf("Input a string:\n");
gets(s);
count=CountRepeatStr(s,&tag);
printf("%c:%d\n",s[tag],count);
return 0;
}
int CountRepeatStr(char str[], int *tag)
{
int l=strlen(str);
int i;
int max=1;
int count=1;
for(i=0;i<l;i++)
{
if(str[i] == str[i+1])
{
count++;
if(count>max)
{
max=count;
*tag=i+1;
}
}
else if(str[i]!=str[i+1])
{
count=1;
}
}
return max;
}
(可以小小的注意一下这道题的算法)
再总结一下这个程序中tag的用法:
主函数给被调函数传的值为tag这个变量的地址,而在被调函数中定义了一个新的变量也叫tag,里面存放的是原函数tag参数的地址,被调函数中的*tag
就相当于访问了主函数tag变量的值(被调函数跟主函数中的tag变量不一样)
这个函数并没有再多专门定义一个指针变量,需要加深理解。