C语言-函数传参

目录

[一. 函数的参数传递](#一. 函数的参数传递)

[1.1 变量传参](#1.1 变量传参)

[1.2 数组传参](#1.2 数组传参)

[1.3 整型数组的几个练习](#1.3 整型数组的几个练习)

[1.4 字符数组的几个练习](#1.4 字符数组的几个练习)

[二. 函数递归](#二. 函数递归)

[2.1 递归求阶乘](#2.1 递归求阶乘)

[2.2 递归的其他几个练习](#2.2 递归的其他几个练习)

[2.2.1 斐波那契数列](#2.2.1 斐波那契数列)

[2.2.2 my_strlen](#2.2.2 my_strlen)

[2.2.3 字符串逆序](#2.2.3 字符串逆序)

[2.2.4 顺序打印整型数](#2.2.4 顺序打印整型数)

[三. 几个常用函数](#三. 几个常用函数)

[3.1 atoi](#3.1 atoi)

[3.2 sprintf](#3.2 sprintf)

一. 函数的参数传递

1.1 变量传参

注意函数传参时:1、保证传递参数个数一样

2、保证传递的类型匹配

示例代码:

cpp 复制代码
int Add(int x,int y)
{
    return x + y;
}

int main()
{
    int a = 10, b = 30;
    int ret = Add(a,b);
    return 0;
}

函数传参的具体过程

**注意:**函数传参采用传值时,形参只是实参的一份临时拷贝,改变形参并不能改变实参。

传值调用 : 实参把参数数据的内容通过赋值运算符给形参的形式。 形参是实参的一个副本(复制

品)。数据内容是相同的,实参的内存空间,和形参的内存,是独立。 没有办法通过修改形参来达

到修改实参的目的。值传递只能读取实参的值, 不能就行修改。
传址调用 :实参传递变量的内存地址值。 即可以读实参的数据的值 ,也可以修改。(数组的传参实际上就是传地址)

eg:下面的代码并不能实现两数交换

cpp 复制代码
void swap(int a,int b)
{
    int c = a;
    a = b;
    b = c;
    printf("swap:a = %d,b = %d\n",a,b);
}

int main()
{
    int a = 10, b = 20;
    printf("before:a = %d,b = %d\n",a,b);
    swap(a,b);
    printf("main:a = %d,b = %d\n",a,b);

    return 0;
}

1.2 数组传参

cpp 复制代码
void arr_fill(int a[],int size)
{
    //如果传参是数组类型,在被调内部,会被降级为指针(8字节)
    int i = 0;
    for(i = 0; i < size; i++)
    {
        a[i] = rand() % 20;//不是传值调用,所以可以修改
    }
   // printf("a size is %lu\n",sizeof(a));
}
void arr_print(int a[],int size)
{
    int i = 0;
    for(i = 0; i < size; i++)
    {
        printf("%3d  ",a[i]);
        if((i + 1) % 5 == 0)
            puts("");
    }
}

int main()
{
    srand(time(NULL));
    int arr[25];
    int size = sizeof(arr) / sizeof(arr[0]);
    arr_fill(arr,size);
    arr_print(arr,size);

    return 0;

}

1、数组传参时在被调函数内部会被降级为指针,在64位系统中大小是8字节,32位系统中大小是4字节。

2、int arr[10] 这个数组arr的类型是:int [10];

3、数组传参时是传址,故在函数内部可以对数组进行改变

4、在被调函数内部不可计算数组的大小,sizeof(arr) = 8/4。应该在主函数计算之后传参给被调函数

1.3 整型数组的几个练习

填充与打印数组:

cpp 复制代码
void arr_fill(int a[],int size)
{
    //如果传参是数组类型,在被调内部,会被降级为指针(8字节)
    int i = 0;
    for(i = 0; i < size; i++)
    {
        a[i] = rand() % 20;//不是传值调用,所以可以修改
    }
   // printf("a size is %lu\n",sizeof(a));
}
void arr_print(int a[],int size)
{
    int i = 0;
    for(i = 0; i < size; i++)
    {
        printf("%3d  ",a[i]);
      //  if((i + 1) % 5 == 0)
          //  puts("");
    }
    puts("");
}

反转数组:

cpp 复制代码
void reverse_arrry(int a[],int size)
{
    int i = 0;
    for(i = 0;i < size / 2; i++)
    {
        int temp = a[i];
        a[i] = a[size - 1 - i];
        a[size - 1 - i] = temp;
    }
}

对数组中的数据进行排序:

cpp 复制代码
//插入排序
void insert_sort(int a[],int size)
{
    int i, j;
    for(i = 0; i < size - 1; i++)
    {
        j = i + 1;
        int temp = a[j];
        while(j > 0 && a[j - 1] > temp)
        {
            a[j] = a[j - 1];
            j--;
        }
        a[j] = temp;
    }
}

//冒泡排序
int bubble_sort(int a[],int size)
{
    int i, j;
    for(i = 1; i < size; i++)
    {
        int flag = 0;
        for(j = 0; j < size - i ;j++)
        {
            if(a[j] > a[j+1])
            {
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
                flag = 1;
            }
        }
        if(flag == 0)
            break;
    }
    return 0;
}

//选择排序
int chose_sort(int a[],int size)
{
    int i, j;
    for(i = 0; i < size - 1;i++)
    {
        for(j = i + 1;j < size;j++)
        {
            if(a[j] < a[i])
            {
                int temp = a[j];
                a[j] = a[i];
                a[i] = temp; 
            }
        }
    }
    return 0;
}

1.4 字符数组的几个练习

实现strlen

cpp 复制代码
nt my_strlen(char a[])
{
    int len = 0;
    while(a[len])
    {
        len++;
    }
    return len;
}

实现strcpy

注意strcpy与memcpy的区别:

strcpy会将**'\0'**也一同拷贝到dst,而memcpy则根据指定的count去拷贝数据。

cpp 复制代码
int my_strcpy(char dst[],char src[])
{
    int i = 0, j = 0;
    while(src[i])
    {
        dst[j++] = src[i++];
    }
    dst[i] = '\0';

    return 0;
}

实现strcat

cpp 复制代码
int my_strcat(char dst[],char src[])
{
    int i = 0, j = 0;
    while(dst[i])
    {
        i++;
    }
    while(src[j])
    {
        dst[i++] = src[j++];
    }
    dst[i] = '\0';
    return 0;
}

实现strcmp

cpp 复制代码
int my_strcmp(char str1[],char str2[])
{
    int i = 0, j = 0;
    while(str1[i] == str2[j] && str1[i] != '\0')
    {
        i++;
        j++;
    }
    return str1[i] - str2[j];
}

二. 函数递归

在函数内部,自己调用自己的函数调用,被称为函数的递归。

属于循环的一种表现形式。但会使用栈空间

注意:需要设置合理的退出条件。递归的层次不要太深,会消耗大量的内存,可能导致程序崩溃。应用,回溯类,逆向思维的问题的。

注意:Linux栈区仅8M,死递归会出现段错误:

2.1 递归求阶乘

cpp 复制代码
int fun(int n)
{
    if(1 == n || 0 == n)
        return 1;
    else
        return fun(n-1) * n;
}

函数递归展开图:

2.2 递归的其他几个练习

2.2.1 斐波那契数列

cpp 复制代码
int Fib(int n)
{
    if(n == 1 || n == 2)
        return 1;
    return Fib(n - 1) + Fib(n - 2);
}

2.2.2 my_strlen

cpp 复制代码
int my_strlen(char *a)
{
    if(*a == '\0')
        return 0;
    return 1 + my_strlen(a+1);
}

2.2.3 字符串逆序

cpp 复制代码
void reverse(char *a,int left,int right)
{
    if(left < right)
    {
        char temp = a[left];
        a[left] = a[right];
        a[right] = temp;
        reverse(a,left+1,right-1);
    }
}

2.2.4 顺序打印整型数

cpp 复制代码
void print(int a)
{
    if(a < 10)
        printf("%d ",a);
    else
    {
        print(a / 10);
        printf("%d ",a % 10);
    }
}

三. 几个常用函数

3.1 atoi

描述:C 库函数 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)

返回值:该函数返回转换后的长整数,如果没有执行有效的转换,则返回零。

3.2 sprintf

描述:`sprintf` 函数会将一系列字符和值格式化并存储在缓冲区中。每个参数(如果有)都会根据 `format` 中对应的格式说明进行转换并输出。格式由普通字符组成,其形式和功能与 `printf` 的格式参数相同。在写入最后一个字符后会添加一个空字符。如果在重叠的字符串之间进行复制,其行为是未定义的。

返回值:如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。

相关推荐
洛水水8 小时前
【力扣100题】18.随机链表的复制
算法·leetcode·链表
南宫萧幕8 小时前
规则基 EMS 仿真实战:SOC 区间划分与 Simulink 闭环建模全解
算法·matlab·控制
爱滑雪的码农9 小时前
Java基础十七:数据结构
数据结构
多加点辣也没关系9 小时前
数据结构与算法|第二十三章:高级数据结构
数据结构·算法
孬甭_11 小时前
初识数据结构与算法
数据结构
hoiii18711 小时前
孤立森林 (Isolation Forest) 快速异常检测系统
算法
InfinteJustice12 小时前
踩坑分享C 语言文件操作全攻略:从基础读写到随机访问与缓冲区原理
c语言·开发语言·microsoft
c++之路12 小时前
适配器模式(Adapter Pattern)
java·算法·适配器模式
吴声子夜歌12 小时前
Java——接口的细节
java·开发语言·算法