关于C语言函数的简单理解

关于C语言函数的简单理解

C语言中的函数

在C语言中,函数是构成程序的基本模块。程序的执行从main()函数的入口开始,到main()函数的出口结束,中间循环、往复、迭代的调用一个有一个函数。每个函数分工明确,各司其职,main函数就像是一个总管。虽然main函数有点特殊,但还是可以从使用者的角度对函数分类,将函数分为标准库函数自定义函数两类。

标准库函数

C语言提供了一些常用的标准库函数,如printf(),scanf()等。符合ANSI C标准的C语言编译器,都必须提供这些库函数。当然,函数的行为也要符合ANSI C的定义。使用ANSI C的库函数,必须在程序的开头把该函数所在的头文件包含进来。例如,使用在math.h内定义的fabs()函数时,只要在程序开头将头文件<math.h>包含到程序中即可。

自定义函数

如果库函数不能满足程序设计者的编程需要,那么就需要自行编写函数来完成自己所需要的功能,这类函数成为自定义函数。

函数定义的基本格式

和使用变量一样,函数使用前必须先定义。函数定义的基本格式为:

返回值类型 函数名(类型 形式参数1,类型 形式参数2,……)
{
	声明语句序列
	可执行语句序列
}

在主函数(main函数)中调用自定义函数的基本格式为:
1.返回值类型为空(void)时:

函数名(实际参数1,实际参数2,……);

2.返回值类型不为空时:

与返回值类型相同的变量 = 函数名(实际参数1,实际参数2,……);

或直接对函数的返回值进行操作,如返回值为int型时,可以有:

 printf("%d", 函数名(实际参数1,实际参数2,……));

这时执行的操作是直接打印出函数的返回值。
示例:
例1.编写一个自定义函数,实现打印Hello World!的功能

#include<stdio.h>

void Print() {
   printf("Hello World!");
}

int main() {
   Print();
   return 0;
}

一个返回值为空(void)的自定义函数,因为自定义函数Print()执行的结果并未产生任何有效数值,并且结合该函数的功能,该函数执行时并不需要外界提供参数才能运行,故函数的传参框内也为空 。
例2.编写一个自定义函数,实现计算a+b的和并返回的功能

#include<stdio.h>
int calculate(int a, int b) {
  int sum;
  sum = a + b;
  return sum;
}
int main() {
  int a, b;
  int sum;
  scanf("%d %d", &a, &b);
  sum = calculate(a, b);
  printf("%d\n", sum);
  return 0;
}

很明显,这是一个返回值为int型的自定义函数,故此我们在main函数中声明一个int型变量sum用来接收函数calculate()的返回值;而该自定义函数想要正常运行就无法缺少a和b两个参数值,所以就通过传参的方式从main函数中将a和b的参数值传入自定义函数中,这个传参的过程相当于一个数据拷贝的过程,即将main函数中a,b的值复制给calculate()函数中的a,b。

C语言函数中的参数传递

通过上面的简单介绍,相信大家对C语言中的函数已经有了简单的理解,那么我们接下来就简单讲一下C语言函数中的参数传递。

参数传递,是在程序运行过程中,实际参数就会将参数值传递给相应的形式参数,然后在函数中实现对数据处理和返回的过程,方法有3种方式

  • 值传递

  • 地址传递

  • 引用传递(C++)

    注意:

  • 被调用函数的形参只有函数被调用时才会临时分配存储单元,一旦调用结束占用的内存便会被释放

  • 值传递和地址传递,传递的都是实参的一个拷贝

  • C语言中实参和形参之间的数据传递是单向的“值传递”,单向传递,只能由实参传给形参,反之不行

  • 输出格式并没有选择%p而是选择了%d,因为十进制的数看起来更直观

值传递:

#include <stdio.h>
  //值传递传值
void swap( int x, int y);
int main()
{
  int a=2,b=3;
  printf("before:实参为a,b\na=%d,地址为%d\nb=%d,地址为%d\n\n",a,&a,b,&b);
  swap(a,b);
  printf("after:实参为a,b\na=%d,地址为%d\nb=%d,地址为%d\n\n",a,&a,b,&b);
  return 0;
}
void swap(int x,int y)
{
  int tmp;
  tmp=x;
  x=y;
  y=tmp;
  printf("inside:形参为x,y\nx=%d,地址为%d\ny=%d,地址为%d\n\n",x,&x,y,&y);
}

执行结果:
在这里插入图片描述
通过示例的执行结果我们可以发现,自定义函数中声明的变量x,y与main函数中的变量a,b的地址值显然不同;即变量x,y其实就是自定义函数声明用来接收实际参数值的形式参数,即a把其值2复制下来传递给了x,b把其值3复制下来传递给了y,这个过程并不对a,b自身的值产生任何影响,只是单纯使形式参数x,y得到一个与实际参数相等的值。
在swap()函数执行完交换x,y的值的操作后,我们可以发现,x,y的值已经相互交换了,而通过打印的数据可以发现a,b的值并没有发生任何改变。这是因为swap函数中的交换操作实际上只是针对x的地址6684128和y的地址6684136这两个内存地址上所储存的数据进行交换,整个过程根本不涉及a,b内存地址上的数据。即在该程序中,在a,b对x,y传参操作结束后,x,y的任何操作都和a,b没有任何关系了,就像两个克隆人,无论做什么事(如光打游戏不学习),都不会对其本体的(学习成绩)产生影响。

地址传递:

#include <stdio.h>
  //地址传递
void swap( int *x, int *y);
int main()
{
  int a=2,b=3;
  printf("before:实参为&a,&b\na=%d,地址为%d\nb=%d,地址为%d\n\n",a,&a,b,&b);
  swap(&a,&b);
  printf("after:实参为&a,&b\na=%d,地址为%d\nb=%d,地址为%d\n\n",a,&a,b,&b);
  return 0;
}
void swap(int *x,int *y)
{
  int tmp;
  tmp=*x;
  *x=*y;
  *y=tmp;
      printf("inside:形参为*x,*y\n*x=%d,x=%d,地址为%d\n*y=%d,y=%d,地址为%d\n\n",*x,x,&x,*y,y,&y);
}

执行结果:
在这里插入图片描述
话接上文,如果我们想让对形式参数所执行的结果作用到实际参数的身上,那该怎么办呢?刚才我们已经提到了,变量是否参与一个操作主要看其所在内存地址的数据是否参与了这个操作;那么我们就直接让实际参数内存地址所存储的数据参与运算不就行了?所以在传地址传参时,我们向自定义函数传递的是实际参数的地址值,而形式参数自然也就是用来储存地址值的指针变量。
由执行结果可以看出,x,y存储的实际上是a和b的地址值,所以此时进行交换数值的操作实际上就是对a,b进行互换操作。传地址传参就是通过对实参内存地址数据的直接操作,来实现函数对实参的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值