C语言函数基础

一.函数的定义

    函数头:函数对外的公开接口
        函数名称:命名规则与跟变量一致,一般取与函数实际功能相符合的、顾名思义的名称。
                    1.只能以数字,字母,下划线组成,首字符不能是数字
                    2.函数名不能重复
                    3.命名的时候,最好一看就知道这个功能是干嘛的, 不要使用a,b,c,d这些单字母的, 不用拼音作为函数名

        参数列表:即黑箱的输入数据列表,一个函数可有一个或多个参数,也可以不需要参数。
                    例如:   买装备, 需要传递2个信息, ①买什么装备  ②有多少钱
                                
        返回类型:即黑箱的输出数据类型,一个函数可不返回数据,但最多只能返回一个数据。
                    作用: 用于返回黑箱执行的结果
        
        函数体:函数功能的内部实现
 

语法:
返回类型 函数名( 参数1, 参数2, 参数3, ... )
{
    函数体;
}

例子:
1. 对比2个数值大小的函数
int Compare( int num1, int num2)
{
    int retval = 0;
    retval = num1 > num2 ? num1 : num2;
    
    return retval;
}

语法汇总:
当函数的参数列表为 void 时,表示该函数不需要任何参数。
当函数的返回类型为 void 时,表示该函数不返回任何数据。
关键字 return 表示退出函数。
        ①若函数头中规定有返回数据类型,则 return 需携带一个类型与之匹配的数据;
        ②若函数头中规定返回类型为 void,则 return 不需携带参数。

    例子:
            申请一片内存空间,并且返回内存的起始地址
错误:        int RequestMemory( int size)            --> 返回类型--int
            {
                int *p = (int *)malloc( size);
                return p;                            --> p:类型int * , 与返回类型不匹配
            }

正确:        int* RequestMemory( int size)            --> 返回类型--int*
            {
                int *p = (int *)malloc( size);
                return p;                            --> p:类型int * , 与返回类型匹配
            }
            

        例子:
            不需要传递参数,与不需要返回结果
错误:        void fun( void )
            {
                ......
                if()
                {
                    return 1;        //由于返回类型是void, 但是返回一个结果,报错
                }
                .....
            }            
            
正确:        void fun( void )
            {
                ......
                if()
                {
                    return ;        //由于返回类型是void, 所以直接使用return就可以退出
                }
                .....
            }
            
            
            


二.实参与形参

    函数调用中的参数,被称为实参,即 arguments
    函数定义中的参数,被称为形参,即 parameters
实参与形参的关系:
    实参于形参的类型和个数必须一一对应。
    形参的值由实参初始化。
    形参与实参位于不同的内存区域,彼此独立。            
    
            
实参于形参的类型和个数必须一一对应。
     

例子:
int add( int a, int b)            //函数定义, num1,num2是形参
{
    a++;
    return a+b;
}

int main()
{
    int a=1,b=2;
    int retval = add( a ,b);            //函数调用, a,b 是实参
    printf("返回的结果:%d\r\n",retval);
}    
调用add完成后,main函数中的a是1

    
练习:            
实现一个传递2个值,把2个值交换的函数,并且在main函数调用,执行完毕后在main函数中打印出来.
 

void fun( int *a, int *b)
{
    int t;
    t  = *a; //a指针指向的内存空间中的数据赋值t
    *a = *b; //b指针指向的内存空间中的数据赋值给a指针指向的内存空间
    *b = t;

}

void fun1( int a, int b)
{
    int t;
    t = a;
    a = b;
    b = t;

}


int main()
{
    int a=1, b=2;
    fun( &a, &b);
    printf("a=%d b=%d\n",a,b);        //输出结果:a=2,b=1, 发生交换

    fun1( a, b);
    printf("a=%d b=%d\n",a,b);        //输出结果:a=2,b=1,    没有发生交换
}            
       

           
函数名  :   可以代表函数的内存地址            
函数指针:     指向与保存代码的内存空间的指针,可以使用该指针进行调用函数。    
语法:
            返回类型 (*指针名)( 参数类型1, 参数类型2, 参数类型3 ... );
           

void fun( int a, int b);
根据函数名写出对应函数指针的方法:    
① 去掉函数名,参数列表的参数名[ 保留参数类型]    void ( int, int);
② 添加指针的变量名,但是一定要使用圆括号            void (*p)( int ,int);             
            
        
函数:       int  fun( int a, int b);
函数指针:   int (*p)( int, int);
            指向 返回值int类型,参数列表中2个参数,分别int,int的函数

函数:       void fun( void (*p)(int ,int), int a, int b);
函数指针:   void (*p)( void (*)(int ,int), int, int);

                
函数指针:       void *(*start_routine) (void *)
函数:           void* fun(void *arg);


三.回调函数:

函数实现方不调用该函数,而由函数接口提供方间接调用的函数,称为回调函数。

例子:

int Compare1( int num1, int num2)
{
    printf("使用if语句判断大小\r\n");
    if( num1 > num2)
        return num1;
    else
        return num2;
}

int Compare2( int num1, int num2)
{
    printf("使用三目运算符判断大小\r\n");
    
    return num1>num2?num1:num2;
}

void Compare( int (*p)( int ,int), int num1, int num2);
{
    printf(    "回调函数的执行\r\n");
    p( num1, num2);
}

int main()
{
    int a =1, a=2;
    Compare( Compare1, a, b);
    Compare( Compare2, a, b);

}

  函数调用的流程

函数调用时,进程的上下文会切换到被调函数,当被调函数执行完毕之后再切换回去

函数调用时代码的执行流程


使用对应函数,称为函数调用.
语法:
    变量 = 函数名( 参数1, 参数2, ... );

例子:
int add( int num1, int num2)            //函数定义
{
    return num1+num2;
}

int main()
{
    int a=1,b=2;
    int retval = add( a, b);            //函数调用
    printf("返回的结果:%d\r\n",retval);
}    

局部变量与栈内存
·局部变量概念:凡是被一对花括号包含的变量,称为局部变量
·局部变量特点:
        某一函数内部的局部变量,存储在该函数特定的栈内存中
        局部变量只能在该函数内可见,在该函数外部不可见

        当该函数退出后,局部变量所占的内存立即被系统回收,因此局部变量也称为临时变量。

        函数的形参虽然不被花括号所包含,但依然属于该函数的局部变量、

·栈内存特点:
        每当一个函数被调用时,系统将自动分配一段栈内存给该函数,用于存放其局部变量

        每当一个函数退出时,系统将自动回收其栈内存
        系统为函数分配栈内存时,遵循从上(高地址)往下(低地址)分配的原则

int max(int x,int y)     // 变量 x 和 y 存储在max()函数的栈中
{ 

int z;            // 变量 z 存储在max()函数的栈中
z = x>y ? x:y;
return z;       // 函数退出后,栈中的x、y 和 z 被系统回收 

}

int main(void)
{

int a = 1;         // 变量 a 存储在main()函数的栈中
int b = 2;        // 变量 b 存储在main()函数的栈中
int m;           //变量 m 存储在main()函数的栈中,未赋值因此其值为随机值
m = max(a, b);

}

函数调用时代码的执行流程

技术要点:
        栈内存相对而言是比较小的,不适合用来分配尺寸太大的变量
        return 之后不可再访问函数的局部变量,因此返回一个局部变量的地址通常是错误的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值