C语言笔记之函数

文章目录

一、库函数

  1. 使用库函数,必须包含 #include 对应的头文件
  2. 学习库函数用到的文档::www.cplusplus.com

二、自定义函数

自定义函数的参数--实参&形参
自定义函数的调用--传值调用&传址调用

用下面例子来演示实参形参以及函数的调用

错误实现方式:
swap1(a, b); 使用传值调用
  • 传值调用时函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
  • 形参实例化之后其实相当于实参的一份临时拷贝。
  • 形参,实参有不同的内存单元
c 复制代码
void swap1(int x, int y)
{
	int z = 0;
	z = x;
	x = y;
	y = z;
	printf("2交换后的a,b为%d %d\n", x, y);//20 10
}
int main()
{
	int a = 10;
	int b = 20;
	printf("1交换前的a,b为%d %d\n", a, b);//10 20
	//即传值调用时函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
	//形参实例化之后其实相当于实参的一份临时拷贝。
	swap1(a, b);//只传变量的值不行的,
	printf("3交换后的a,b为%d %d\n", a, b);//10 20
	return 0;
}
正确的实现方式:
swap2(&a, &b); 使用传址调用
  • 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
  • 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
  • 即用px,py指针变量来操作a,b变量
c 复制代码
void swap2(int *px, int *py)
{
    int z = 0;
    z = *px;//将px指针变量进行解引用即得到的是a变量的值10
    *px = *py;
    *py = z;
    printf("2交换后的a,b为%d %d\n", *px, *py);//20 10
}
int main()
{
    int a = 10;
    int b = 20;
    printf("1交换前的a,b为%d %d\n", a, b); // 10 20
    // 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
    // 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
    // 即用px,py指针变量来操作a,b变量
    swap2(&a, &b);
    printf("3交换后的a,b为%d %d\n", a, b); // 20 10
    return 0;
}

三、函数的嵌套调用

函数不可以进行嵌套定义
c 复制代码
void new_line()
{
    printf("hehe\n");
}
void three_line()
{
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        new_line();
    }
}
int main()
{
    three_line(); // 主程序调用three_line(),three_line()调用new_line()
    return 0;
}

四、函数的链式访问--需要函数必须要有返回值

例1:
  • strcat()用于将源字符串追加到目标字符串末尾,并自动在结果末尾添加 \0 结束符
  • 用strlen()和sizeof()求数组中元素个数的区别
  • 对数组使用不同初始化方式会对使用sizeof()求数组中元素个数产生影响
c 复制代码
int main()
{
    char arr[20] = "hello";
    // strcat()用于将源字符串追加到目标字符串末尾,并自动在结果末尾添加 \0 结束符
    int ret = strlen(strcat(arr, "bit"));
    printf("%d\n", ret); // 8,不算\0 用sizeof()求会算\0
    int ret1 = sizeof(arr) / sizeof(arr[0]);
    printf("%d\n", ret1); // 20,因为数组大小是20,没放数据的单元默认放值了\0

    char arr1[] = "hello";
    int ret2 = sizeof(arr1) / sizeof(arr1[0]);
    printf("%d\n", ret2); // 6,因为数组大小是5个字母+\0 = 6
    return 0;
}
例2:
  • printf函数的返回值是打印在屏幕上字符的个数
c 复制代码
int main()
{
	//printf函数的返回值是打印在屏幕上字符的个数
	printf("%d", printf("%d", printf("%d", 43)));//4321
	return 0;
}

五、练习

写一个函数,实现一个整形有序数组的二分查找。
正确写法:
  • 函数传参时必须将数组中元素个数做为实参传递(因为数组传参实际上传递的是数组首地址,不是整个数组所以不能在binarySearch函数内部来计算数组的元素个数)
c 复制代码
int binarySearch(int arr[], int arrnum, int num)
{
    int left = 0;
    int right = arrnum - 1;
    int i = 0;
    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        if (arr[mid] > num)
        {
            right = mid - 1;
        }
        else if (arr[mid] < num)
        {
            left = mid + 1;
        }
        else
        {
            return mid;
        }
    }
    if (left > right)
    {
        return -1;
    }
}
int main()
{
    int num = 0;
    printf("请输入数字:\n");
    scanf("%d", &num);
    int arr[8] = {1, 3, 7, 9, 15, 36, 47, 58};
    int arrnum = sizeof(arr) / sizeof(arr[0]);
    // 注意这里必须将数组中元素的个数做为参数传递,
    // 因为数组传参实际上传递的是数组首地址,不是整个数组所以不能在binarySearch函数内部来计算数组的元素个数
    int index = binarySearch(arr, arrnum, num);
    if (-1 != index)
    {
        printf("找到了,索引是%d\n", index);
    }
    else
    {
        printf("找不到\n");
    }
    return 0;
}
错误写法:
  • 在binarySearch函数内部来计算数组的元素个数会发现得到的结果为1或者2(由机器字长决定)
c 复制代码
int binarySearch(int arr[], int num)
{
    int left = 0;
    // 如果在binarySearch函数内部来计算数组的元素个数会发现数组传参实际上传递的是数组首地址
    // 64位机器指针是8字节而int型元素的大小是4字节 所以arrnum==2
    int arrnum = sizeof(arr) / sizeof(arr[0]);
    printf("arrnum:%d\n", arrnum); // 2
}
int main()
{
    int num = 0;
    printf("请输入数字:\n");
    scanf("%d", &num);
    int arr[8] = {1, 3, 7, 9, 15, 36, 47, 58};
    // int arrnum = sizeof(arr) / sizeof(arr[0]);
    //  注意这里必须将数组中元素的个数做为参数传递,
    //  因为数组传参实际上传递的是数组首地址,不是整个数组所以不能在binarySearch函数内部来计算数组的元素个数
    int index = binarySearch(arr, num);
    return 0;
}
相关推荐
杜子不疼.2 小时前
基于ATVC模板库的Ascend C Vector算子快速开发指南
c语言·开发语言·mfc
四谎真好看2 小时前
JavaWeb学习笔记(Day13)
笔记·学习·学习笔记·javaweb
C++ 老炮儿的技术栈2 小时前
Qt Creator中不写代如何设置 QLabel的颜色
c语言·开发语言·c++·qt·算法
承渊政道3 小时前
Linux系统学习【Linux基础开发工具】
linux·运维·笔记·学习·centos·编辑器
艾莉丝努力练剑3 小时前
【Linux:文件】基础IO
linux·运维·c语言·c++·人工智能·io·文件
you-_ling3 小时前
IO编程相关知识
c语言·vscode
小龙报3 小时前
【51单片机】深度解析 51 串口 UART:原理、配置、收发实现与工程化应用全总结
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·51单片机
承渊政道3 小时前
C++学习之旅【C++中模板进阶内容介绍】
c语言·c++·笔记·学习·visual studio
浅念-3 小时前
C语言——动态内存管理
c语言·开发语言·c++·笔记·学习