• 32 函数的意义


    1 C 语言中的函数

    • 函数的由来
      • 程序 = 数据 + 算法
      • C 程序 = 数据 + 函数

    2 函数的意义

    • 模块化程序设计

    • C 语言中的模块化

    3 面向过程的程序设计

    • 面向过程是一种以过程为中心的编程思想
    • 首先将复杂的问题分解为一个个容易解决的问题
    • 分解过后的问题可以按照步骤一步步完成
    • 函数是面向过程在 C 语言中的体现
    • 解决问题的每个步骤可以用函数来实现

    4 声明和定义

    • 声明和定义并不相同

    • 声明的意义在于告诉编译器程序单元的存在

    • 定义则明确指示程序单元的意义

    • C 语言中通过 extern 进行程序单元的声明

    • 一些程序单元声明时可以省略 extern

    • 示例:声明和定义的不同

      • Demo1

        // test.c
        #include <stdio.h>
        #include <malloc.h>
        
        //声明外部全局变量,在其他C文件中被定义,编译器在此处不会给g_var分配空间
        extern int g_var;
        
        //声明外部全局结构体,在其他C文件中被定义
        extern struct Test;
        
        int main()
        {
            //声明函数,在其他C文件中被定义
            extern void f(int i, int j);
            extern int g(int x);
            
            struct Test* p = NULL; // (struct Test*)malloc(sizeof(struct Test));
            
            printf("p = %p
        ", p);
            
            g_var = 10;
            
            printf("g_var = %d
        ", g_var);
            
            f(1, 2);
            
            printf("g(3) = %d
        ", g(3));
            
            free(p);
            
            return 0;
        }
        
        
        //global.c
        #include <stdio.h>
        
        int g_var = 5;
        
        struct Test
        {
            int x;
            int y;
        };
        
        void f(int i, int j)
        {
            printf("i + j = %d
        ", i + j);
        }
        
        int g(int x)
        {
            return (int)(2 * x + g_var);
        }
        
      • 编译:struct 不需要使用 extern 进行声明

        test.c:6: warning: useless storage class specifier in empty declaration
        
      • 运行

        p = (nil)
        g_var = 5
        g_var = 10
        i + j = 3
        g(3) = 16
        
      • Demo2:修改 p 指针指向的内存分配方式

        // test.c
        #include <stdio.h>
        #include <malloc.h>
        
        extern int g_var;
        
        extern struct Test;
        
        int main()
        {
            extern void f(int i, int j);
            extern int g(int x);
            
            struct Test* p = (struct Test*)malloc(sizeof(struct Test));
            
            printf("p = %p
        ", p);
            
            g_var = 10;
            
            printf("g_var = %d
        ", g_var);
            
            f(1, 2);
            
            printf("g(3) = %d
        ", g(3));
            
            free(p);
            
            return 0;
        }
        
        
        //global.c
        #include <stdio.h>
        
        int g_var = 5;
        
        struct Test
        {
            int x;
            int y;
        };
        
        void f(int i, int j)
        {
            printf("i + j = %d
        ", i + j);
        }
        
        int g(int x)
        {
            return (int)(2 * x + g_var);
        }
        
      • 编译

        • 分析:编译器编译文件的顺序是不确定的,那么编译器在编译 test.c 文件时,编译到 14 行时无法知道结构体 Test 的大小信息
        test.c: In function ‘main’:
        test.c:13: error: invalid application of ‘sizeof’ to incomplete type ‘struct Test’ 
        
      • Demo3: g_var 变量的类型在声明和定义时不同

        // test.c
        #include <stdio.h>
        #include <malloc.h>
        
        extern int g_var;
        
        extern struct Test;
        
        int main()
        {
            extern void f(int i, int j);
            extern int g(int x);
            
            struct Test* p = NULL;
            
            printf("p = %p
        ", p);
            
            g_var = 10;
            
            printf("g_var = %d
        ", g_var);
            
            f(1, 2);
            
            printf("g(3) = %d
        ", g(3));
            
            free(p);
            
            return 0;
        }
        
        
        //global.c
        #include <stdio.h>
        
        float g_var = 5;
        
        struct Test
        {
            int x;
            int y;
        };
        
        void f(int i, int j)
        {
            printf("i + j = %d
        ", i + j);
        }
        
        int g(int x)
        {
            return (int)(2 * x + g_var);
        }
        
      • 编译运行:变量 g_var 打印出的值与预期不同

        • 分析:编译器在处理 test.c 文件的第 19 行时,按照 int 的存储方式到 g_var 对应的内存处取值,即将一个二进制的 float 值解释为 int
        p = (nil)
        g_var = 1084227584
        g_var = 10
        i + j = 3
        g(3) = 6
        
  • 相关阅读:
    LinkedList的实现源码分析
    ArrayList实现源码分析
    探索HashMap实现原理及其在jdk8数据结构的改进
    Maven的安装使用以及 Maven+Spring hello world example
    RedisHelper帮助类
    Stream 和 byte[] 之间的转换
    WCF For Silverlight跨域策略
    Linq Query常见错误
    Linq to Sharepoint--如何获取Linq Query 生成的CALM
    如何使用代码备份SQL Server数据库
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13774044.html
Copyright © 2020-2023  润新知