开发者学堂课程【你的第一门 C 语言课:参数和指针】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/444/detail/5495
参数和指针
简介:
一、参数和返回值
二、形参和实参
三、传值和传址
四、传数组
五、可变参数
一、参数和返回值
1.参数的用法和作用
函数是一种封装的方法。函数的设计遵从一个函数仅实现一个功能的原则,便可化繁为简,将复杂的程序拆解开,变成一个个独立的功能。每个功能使用单个函数实现。
函数定义时通过参数列表以指定函数的数量和类型,前者使得后者更加灵活。传入的参数使得函数拥有更为丰富的功能。同时,函数应支持个性化定制
2. 类型名
函数实现功能通常需要反馈结果,但实际操作中并不一定出现,故需要设定一个返回值以观察函数调用是否成功,或者出现了何种问题。若函数的确不需要返回值,则可以使用 void 以表示不返回。
定义函数时,已经确定了参数的数量和类型,但参数数量是可变的。
二、形参和实参
1.定义
形参:形式参数
实参;实际参数
2.举例
#include
int sum(int, int);
int sum(int x,int y)
{
return (x + y);
}
int main()
{
sum(3, 5);
return 0 ;
}
其中,int x,int y 为形参。其仅作为占位符,并无实际的数值。而在函数被调用期间,传与其一个实际的数值,例如3, 5,此为实际数值,被称为实参。
形参与实参均用于数据传输,当函数发生调用时实参的数值将传递给形参,此种传输具有单向性,即不能讲形参的值传输给实参。形参变量定义时仅作为一个占位符,提示需要留存变量并保留空间,并无实际数据的传输,数值仍为随机。只有在函数调用时,数值的位置才会真正生成空间、分配内存。而当函数调用结束后,其又会立刻释放内存。故,形参变量仅在函数内部有效。
三、传值和传址
指针是一个变量,可以通过参数传递给函数。
1.引进指针参数的实际意义
(1).不使用指针的示例:
#include
void swap(int x,int y);
void swap(int x,int y)
{
int temp
printf(“In sawp,互换前:x=%d,y=%d\n”,x,y);
temp=x
x=y
y=temp /*两数交换所需要的中间值*/
printf(“In sawp,互换后:x=%d,y=%d\n”,x,y);
}
int main( )
{
int x=3,y=5;
printf(“In main,互换前:x=%d,y=%d\n”,x,y);
swap(x,y); /*swap:互相交换的含义*/
printf(“In main,互换后:x=%d,y=%d\n”,x,y);
return0;
}
得到结果:
[fishc@bogon sle29]$ gcc testl.c && . /a . out
in main,互换前:x=3,y=3;
in swap,互换前:x=3,y=5;
in swap,互换前:x=5,y=3;
in main,互换前:x=3,y=5;
fishc@bogon sle29] $
//结果与预料相同
(2).使用指针的示例:
[fishc@bogon sle29] $ cp test1.c test2.c
[fishc@bogon sle29] $ vi test2.c
#include
void swap(int *x,int *y);
//指针x,y存放的是数值,对其都要进行解引用
void swap(int *x,int *y)
{
int temp
printf(“In sawp,互换前:x=%d,y=%d\n”,*x,*y);
temp=*x
*x=*y
*y=temp
printf(“In sawp,互换后:x=%d,y=%d\n”,*x,*y);
}
int main( )
{
int x=3,y=5;
printf(“In main,互换前:x=%d,y=%d\n”,x,y);
swap(&x,&y); //指针中存放的必须为地址
printf(“In main,互换后:x=%d,y=%d\n”,x,y);
return0;
}y
得到结果:
[fishc@bogon sle29]$ gcc test2.c && . /a . out
in main,互换前:x=3,y=3;
in swap,互换前:x=3,y=5;
in swap,互换前:x=5,y=3;
in main,互换前:x=5,y=3;
fishc@bogon sle29] $
(3).结论
当不使用指针时,函数内部无法改变实参的值,即内部 (swap) 互换之后,在 main 中的值仍未改变。
由于 C 语言中每个函数都有独立的作用域,即每个函数的内部都是互相独立的,他们的作用旨在函数内部生效,不同函数之间不能直接访问对方的变量。例如 main和 swap 两个作用域中的x,y并不冲突,是不同的两组变量。
2.使用指针能改变的原因
指针中存放的是别人的地址,例如经 main 函数中的 x,y 两个地址传递给形参,则两个形参函数 x,y 即是对两个变量 x,y 的引用。引用后相当于将其地址搬到另一处,直接进行互换。
实现了传值和传址的根本区别。
四、传数组
1.示例一
[fishc@bogon sle29]$ gcc test3.c
#include
void get_array(int a[10]); //array:数组
void get_array(int a[10])
{
int i;
for (i=0;i<10;i++)
{
printf(“a[%d] = %d\n”,i,a[i]);
}
}
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,0};
get_arrayp{a}
return 0 ;
}
查看打印结果:
[fishc@bogon sle29]$ gcc test3.c && ./a.out
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
a[5] = 6
a[6] = 7
a[7] = 8
a[8] = 9
a[9] = 0
[fishc@bogon s1e29]$
在此基础上修改代码:
#include
void get_array(int a[10]);
void get_array(int a[10])
{
int i;
a[5] = 520;
for (i=0;i<10;i++)
{
printf(“a[%d] = %d\n”,i,a[i]);
}
}
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,0};
int i;
get_array(a);
printf(*在main函数中再打印一次...\n*);
for (i=0;i<10;i++)
{
printf(“a[%d] = %d\n”,i,a[i]);
}
return 0 ;
}
若在调用时将整个数组传递进形参中,则两方的 a 同样是独立开的。此情况下的变量将不会被互相修改到。但实际情况如下:
[fishc@bogon sle29]$ gcc test3.c && ./a.out
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
a[5] = 520
a[6] = 7
a[7] = 8
a[8] = 9
a[9] = 0
在main函数里边再打印一次......
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
a[5] = 520
a[6] = 7
a[7] = 8
a[8] = 9
a[9] = 0
[fishc@bogon s1e29]$
此时 fishc 和 main 数组的函数都被改动,说明并不存在将整个数组作为参数传递的方式。接受的仅是地址本身。
2.示例二
[fishc@bogon sle29]$ gcc test4.c
#include
void get_array(int a[10]);
//由于并不是将一个数组传递给过来,此处仅作为验证进行
void get_array(int a[10])
{
printf(“sizeof b: %d\n”,sizeof(b));
}
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,0}
printf(“sizeof a: %d\n”,sizeof(a));
查看结果:
[fishc@bogon sle29]$ gcc test4.c && ./a.out
sizeof a:40
//a是41个元素,每一个整型变量在变异系统中占4个字节,总量为10x4=40字节
sizeof b:4
//仅作为地址,故只占有一个地址应有的尺寸,即4个字节
[fishc@bogon sle29]$
五、可变参数
1.定义
可变参数的实现需要包含头文件,即 stdarg.h,头文件中需要四个元素
#include
一个类型:
va_list-定义字符指针的类型
三个宏:
va_start-对字符指针进行计算
va_arg
va_end
其中,va即variable-argument的缩写
2.示例
[fishc@bogon sle29]$ gcc test4.c
#include
#include
int sum(int n...)
//...表示数目不确定
int sum(int n...)
{
int i,sum = 0;
va_list vap;
//定义参数列表
va_start(vap,n);
//传入宏va_start
for (i = 0;i
{
sum +=va_arg(vap,int);
//利用va_arg获取每一个参数的值、类型
}
va_end(vap); //va_end
关闭参数列表
return sum;
}
int main()
{
int result;
//接收返回的结果
result = sum(3,1,2,3);
printf(“result1 =%d\n”,result);
result = sum(53,1,2,3,4,5);
printf(“result2=%d\n”,result);
result = sum(6,3,-1,-2,4,99,100);
printf(“result3=%d\n”,result);
return 0;
}
查看结果:
[fishc@bogon sle29]$ gcc test5.c && ./a.out
result1 = 6
result2 = 15
result3 = 203
[fishc@bogon sle29]$