C语言-函数

1.函数的概念

函数就是一个完成某项特定的任务的一个小段代码,代码是有特殊的写法和调用方法的。

两类函数:1.库函数    2.自定义函数

2.库函数

2.1 使用方法
double sqrt(double x);
//sqrt是函数名
//x是函数的参数,表示调用sqrt函数需要传递一个double类型的值
//double是返回值类型-表示函数计算的结果是double类型的值
2.1.1 头文件

对于库函数的使用,必须包含对应的文件。

2.1.2 练习
#include<stdio.h>
#include<math.h>

int main()
{
    double d = 16.0;
    double r =sqrt(d);
    printf("%1f\n",r);
    return 0;
}

 3.自定义函数

3.1语法形式

与库函数类似,如下。

ret_type fun_name(形式参数)
{

}

//ret_type是函数返回类型
//fun_name是函数名
括号中是形式参数
{}括起来是函数体
3.2举例

一个加法函数,完成2个整型变量的加法操作。

#include<stdio.h>
int Add(int x,int y) //括号中写的x,y称为形参
{
   int z=0;
   z=x+y;
   return z;
}

int main()
{
   int a=0;
   int b=0;
   scanf("%d %d",&a,&b);
   int r=Add(a,b); //调用函数,这里的a,b为实参
   printf("%d\n",r);
   return 0;
}

4.数组做函数参数

如果写一个函数对将一个整型数组的内容,全部置-1,再写一个函数打印数组的内容。

#include<stdio.h>

int main()
{
   int arr[]={1,2,3,4,5,6,7,8,9,10};
   int sz=sizeof(arr)/sizeof(arr[0]);
   set_arr(arr,sz);//设置数组内容为-1
   printf_arr(arr,sz);//打印数组内容
   return 0;
}

数组作为参数传递给了set_arr 和 print_arr 函数了,那这两个函数应该如何设计呢?
这⾥我们需要知道数组传参的⼏个重点知识:
函数的形式参数要和函数的实参个数匹配
函数的实参是数组,形参也是可以写成数组形式的
形参如果是⼀维数组,数组⼤⼩可以省略不写
形参如果是⼆维数组,⾏可以省略,但是列不能省略
数组传参,形参是不会创建新的数组的
形参操作的数组和实参的数组是同⼀个数组
根据上述的信息,我们就可以实现这两个函数:
void set_arr(int arr[],int sz)
{
    int i=0;
    for(i=0;i<sz;i++)
    {
        arr[i]=-1;
    }
}

void print_arr(int arr[],int sz)
{
    int i=0;
    for(i=0;i<sz;i++)
    {
       printf("%d ",arr[i]);
    }
    printf("\n");
}

5.嵌套调用和链式访问

5.1 嵌套调用

函数之间互相调用。

比如:计算某年某月有几天?如果要函数实现,可以设计2个函数:

is_leap_year() 根据年份确定是否是闰年

get_days_of_month() 调用is_leap_year确定是否是闰年后,再根据月计算这个月的天数

int is_leap_year(int y)
{
   if(((y%4==0)&&(y%100!=0))||(y%400==0))
      return 1;
   else
      return 0;
}

int get_days_of_month(int y,int m)
{
  int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
  int day=days[m];
  if(is_leap_year(y) && m ==2)
     day+=1;

  return day;
}

int main()
{
  int y=0;
  int m=0;
  scanf("%d %d",&y,&m);
  int d=get_days_of_month(y,m);
  printf("%d\n",d);
  return 0;
}

6.链式访问

将一个函数的返回值作为另外一个函数的参数,像链条一样将函数串起来就是函数的链式访问。

比如:

#include<stdio.h>

int main()
{
   int len=strlen("abcdef");//strlen求一个字符串的长度
   printf("%d\n",len);
   return 0;
  
}

如果把strlen的返回值直接作为printf函数的参数呢?这样就是一个链式访问的例子了。

#include<stdio.h>

int main()
{
    printf("%d\n",strlen("abcdef"));//链式访问
    return 0;

}

7. static和extern

static是 静态的 的意思,可以用来:

修饰局部变量

修饰全局变量

修饰函数

extern是用来声明外部符号的。

7.1 static 修饰局部变量:
代码1
#include<stdio.h>
void test()
{
   int i=0;
   i++;
   printf("%d ",i);
}
int main()
{
  int i=0;
  for(i=0;i<5;i++)
  {
      test(); 
  }
  return 0;
}


代码2
#include<stdio.h>
void test()
{
    //static修饰局部变量
    static int i=0;
    i++;
    printf("%d ",i);
}
int main()
{
   int i=0;
   for(i=0;i<5;i++)
   {
       test();
   }
    return 0;

}
对⽐代码1和代码2的效果,理解static修饰局部变量的意义。
代码1的test函数中的局部变量i是每次进⼊test函数先创建变量(⽣命周期开始)并赋值为0,然后
++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)。
代码2中,我们从输出结果来看,i的值有累加的效果,其实test函数中的i创建好后,出函数的时候是
不会销毁的,重新进⼊函数也就不会重新创建变量,直接上次累积的数值继续计算。
结论:static修饰局部变量改变了变量的⽣命周期,⽣命周期改变的本质是改变了变量的存储类型,本
来⼀个局部变量是存储在内存的栈区的,但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量是一样的,生命周期就和程序的生命周期一样,只有程序结束,变量才销毁,内存才回收。但是作用域不变。
如果要一个变量出了函数后,还想保留值,等下次进入函数继续使用,就可以使用static修饰。
 
7.2 extern声明外部符号

代码1:

add.c

int g_val=20;

test.c

#include<stdio.h>
extern int g_val;
int main()
{
    printf("%d\n",g_val);
    return 0;
}

extern是用来声明外部符号的,如果一个全局的符号在A文件中定义的,在B文件中想用,就可以使用extern进行声明,然后使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值