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
      
原文地址:https://www.cnblogs.com/bky-hbq/p/13774044.html