• 一个冒泡排序引发的思考


    ​ 我想大多数人学习C语言的时候都曾经接触过冒泡排序,但是今天冒泡排序的实现并不是引起我思考的地方。当我写好冒泡排序的相关代码,准备将它封装成一个函数的时候,那括号里面的参数引起了我深深的思考。

    #include 
    void maopaos(int arr[],int len) {
        int i, j, t;
        for (i = 0; i < len - 1; i++) {
            for (j = 0; j < len - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    t = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = t;
                }
            }
        }
        for (i = 0; i < len; i++) {
            printf("%d ", arr[i]);
        }
    }
    void mainss() {
        int arr[] = {-1, 2, -3, 3, 7, 8, 1};
        int len = sizeof(arr) / sizeof(int);
        maopaos(arr,len);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    ​ 正如这部分关于冒泡排序的代码当我封装成maopaos(int arr[],int len)函数的时候,我总觉的两个参数很麻烦。毕竟当我要用这个函数进行冒泡排序的时候,直接传一个数组参数多好。maopaos(int arr[ ]).就是最理想的,不需要再添加一个关于数组长度的len.然后我就开始改了,比如这样:

    #include 
    void maopaos(int arr[]) {
        int i, j, t;
        int len = sizeof(arr) / sizeof(int);
        printf("arr数组的长度是:%d\n",len);
        for (i = 0; i < len - 1; i++) {
            for (j = 0; j < len - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    t = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = t;
                }
            }
        }
        for (i = 0; i < len; i++) {
            printf("数组的元素是:%d ", arr[i]);
        }
    }
    void main() {
        int arr[] = {-1, 2, -3, 3, 7, 8, 1};
        maopaos(arr);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    但是当我运行的时候,却出现了缺斤少量的情况。
    在这里插入图片描述

    我这么多元素的数组,最后只剩两个,难道被狗吃了?那么为什么呢?

    接着我写了一个简单的测试代码探究为什么在函数内不能精确算数组的长度:

    #include 
    void suzu(int arr[]){
        //将传入的数组的长度求出
        int len=sizeof (arr)/sizeof (int);
        printf("函数内数组长度%d:",len);
    }
    void main(){
        //定义一个测试数组
        int a[]={1,2,3,45,67,12};
        //求出数组的长度
        int length=sizeof (a)/sizeof (int);
        //将长度输出
        printf("数组长度%d\n",length);
    //调用函数
        suzu(a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果为:

    在这里插入图片描述

    显然函数内的数组长度是不对的

    后来查找了一下关于函数形参的知识:

    默认是引用传递的数据类型有:指针和数组

    所谓引用传递即是:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值)

    那也就意味着suzu(int arr[])里面的arr比不是一个真正意义上的数组,而是一个地址。于是我又开始测试:

    #include 
    void suzu(int arr[]){
        //将传入的数组的长度求出
        int len=sizeof (arr)/sizeof (int);
        printf("函数内数组长度%d:\n",len);
        printf("该函数形参的地址值为%p",arr);
    }
    void main(){
        //定义一个测试数组
        int a[]={1,2,3,45,67,12};
        //求出数组的长度
        int length=sizeof (a)/sizeof (int);
        //将长度输出
        printf("数组长度%d\n",length);
    //调用函数
    printf("a数组的地址值是:%p\n",&a);
        suzu(a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果为:

    在这里插入图片描述

    这就说明了**suzu(int arr[])**中的arr的确是一个存放地址的变量。

    为了进一步论述,我试着通过*arr的操作取到数数组中的元素;

    #include 
    void suzu(int arr[]){
        //将传入的数组的长度求出
        int len=sizeof (arr)/sizeof (int);
        printf("函数内数组长度%d:\n",len);
        printf("该函数形参的地址值为%p\n",arr);
        printf("根据地址取值%d ",*arr);
        printf("%d ",*(arr+1));
        printf("%d ",*(arr+2));
        printf("%d ",*(arr+3));
    }
    void main(){
        //定义一个测试数组
        int a[]={1,2,3,45,67,12};
        //求出数组的长度
        int length=sizeof (a)/sizeof (int);
        //将长度输出
        printf("数组长度%d\n",length);
    //调用函数
    printf("a数组的地址值是:%p\n",&a);
        suzu(a);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    运行结果为:

    在这里插入图片描述

    看到这里也就解释开头冒泡排序需要同时传入数组和数组长度两个形参的原因了:我们再次回到那段代码;

    #include 
    void maopaos(int arr[]) {
        int i, j, t;
        int len = sizeof(arr) / sizeof(int);//求得是形参变量用于存放数组地址的arr的长度。
        printf("arr数组的长度是:%d\n",len);
        for (i = 0; i < len - 1; i++) {
            for (j = 0; j < len - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    t = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = t;
                }
            }
        }
        for (i = 0; i < len; i++) {
            printf("数组的元素是:%d ", arr[i]);
        }
    }
    void main() {
        int arr[] = {-1, 2, -3, 3, 7, 8, 1};
        maopaos(arr);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    也不难解释在函数maopao(int arr[]) 中arr的长度是2.一个存放地址的变量大小当然是2,。

    不过最后还是得掌握函数的传参知识:

    1.默认是引用传递的数据类型有:指针和数组

    2.所谓引用传递即是:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值)

    又加深了一个知识点!

  • 相关阅读:
    REDIS可视化神器 | REDIS DESK MANAGER(2022.5.1)
    智能物联网解决方案:蓝牙IOT主控模块打造高效监测和超低功耗
    ArduinoUNO实战-第五章-有源蜂鸣器实验
    list容器(20221117)
    一种自平衡解决数据倾斜的分表方法
    如何用一颗芯片实现5V转正负12V
    【Java】【多线程】synchronized 关键字
    Base64解码
    playwright自动化上传附件
    Go 代码审计高危漏洞(sqli\cmd\ssrf)
  • 原文地址:https://blog.csdn.net/weixin_55418082/article/details/126356769