• 【C语言】函数三要素,变量作用域、生存周期、存储类型


    目录

    写在前面

    一、函数的用法

    1、声明

    2、调用

    3、定义

    形参与实参类型不一致

    形参与实参类型一致

    函数值类型与返回值类型不一致

    函数值类型与返回值类型一致

    二、变量的作用域与生存周期

    三、变量的储存类型(auto,extern,static,register)

    写在最后


     

    写在前面

    本文不讲一些琐碎的概念,而将其实例化,来解决一些棘手的问题;

    要讲函数,那得从声明、定义、调用、返回讲起


    一、函数的用法

    9027a25297c349a789fb457e7a60e027.png

    第一个函数结构。定义函数放在了调用函数之后,则需要在main函数之前进行声明。

    第二个函数结构。定义函数放在了调用函数之前。那么则无需进行声明。

    习惯问题:因为C语言程序总是从main函数开始,所以尽快找到main函数符合程序阅读的习惯,试想在一个很长的程序中找上半天才能找到main函数是多么不方便。


    在开始之前,我们来问个小问题

    1、void max( int,int );

    2、void max( int a,int b );

    3、max(a,b);

    4、max(a,b)

    上面四个代码,哪是声明,哪是调用,哪是定义

    公布答案:1、2是声明,3是调用,4是定义


    下面的所有实例均以这个代码来解释

    1. #include
    2. void max(int a,int b); //函数声明
    3. int main()
    4. {
    5. int a,b;
    6. max(a,b); //函数调用
    7. return 0;
    8. }
    9. void max(int a,int b) //函数定义
    10. {
    11. if(a>b)
    12. return ;
    13. else
    14. printf("a<=b");
    15. }

    1、声明

    void  max( int a,int a ); 或者void  max( int int );

    返回类型+函数名+(参数类型1,参数类型2,...)

    2、调用

    max(a,b);

    函数名(参数1,参数2),这里的参数是实参

    3、定义

    max(int a,int b){ }

    函数名(类型1+参数1,类型2+参数2,...),这里的参数是形参

    形参与实参类型不一致

    以形参为主,因为编译器只知道形参的类型,不知道实参的类型,会将实参隐式转化为形参的类型

    形参与实参类型一致

    形参只能为变量,不能为常量和表达式,例如void max(7,a+b)就是错误的

    函数值类型与返回值类型不一致

    函数值类型与返回值类型不一致,以函数值类型为准,会把return 语句表达式的值的类型转化为函数值的类型

    函数值类型与返回值类型一致

    return (表达式)  ---->有返回值

    return 表达式    ---->有返回值

    return ;           ---->无返回值(void类型)


    二、变量的作用域与生存周期

    4816848cf2e7468991a2ef945e02d4b4.png

    局部变量全局变量
    1、main()函数内定义的变量也是局部变量,它只能在主函数内使用,但由于程序总是从main函数开始,以main函数执行完毕结束,所以main函数内定义的局部变量生存周期与全局变量相同4、从模块化程序设计的观点来看,这是不利的,一般不要使用全局变量
    2、允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的内存单元5、全局变量与局部变量重名时,全局变量会被屏蔽,要引用需要在变量名前加两个冒号 ::
    3、在复合语句中定义的变量是局部变量,作用域在复合语句(即{}里的一系列语句共同构成)范围内,生存周期是复合语句执行的时间段6、全局变量必须在所有函数之外,若想在定义全局变量之前的位置上使用,需加扩展名extern

     

     

     

     

     

     

     

     

     

     

    概念解释

    1. #include
    2. int fun1(int a,int b);//声明
    3. int fun2(int ,int);
    4. int fun3(int ,int);
    5. int main()
    6. {
    7. int a=3,b=4;//对1的解释
    8. printf("局部变量a=%d\n",a);
    9. printf("全局变量a=%d\n",::a);//对5的解释
    10. fun1(a,b);
    11. fun2(a,b);
    12. fun3(a,b);//函数调用
    13. return 0;
    14. }
    15. extern int d=10;//对6的解释,让fun1也能用d=4
    16. int fun1(int a,int b)//对2的解释
    17. {
    18. int c=0;//对3的解释,其他函数不能用c
    19. }
    20. int d=10;//全局变量,fun2之后的函数能用
    21. int fun2(int a,int b)//对2的解释
    22. {
    23. ...
    24. }
    25. int fun3(int a,int c)
    26. {
    27. ...
    28. }

    三、变量的储存类型(auto,extern,static,register)

    de9e6178514a41519d0d5b3d138db89c.png

    有关储存区的相关内存概念,大家自行搜索了解。

    那我们平时做练习写的程序都是定义的什么变量呢?我们来看看吧

    1. #include
    2. int fun1(int a,int b);//声明
    3. int fun2(int ,int);
    4. int fun3(int ,int);
    5. int main()
    6. {
    7. static int a=3,b=4; //静态局部变量
    8. printf("局部变量a=%d\n",a);
    9. printf("全局变量a=%d\n",::a);
    10. fun1(a,b);
    11. fun2(a,b);
    12. fun3(a,b);//函数调用
    13. return 0;
    14. }
    15. extern int d;//一旦把前缀写出来,就容易把定义和扩展搞混,
    16. //全局变量只能定义一次,没有赋值的就是扩展,赋值的就是定义
    17. int fun1(int a,int b)
    18. {
    19. auto int c=0;//局部变量的默认存储方式是auto
    20. }
    21. extern int d=10;//全局变量默认存储方式是extern
    22. int fun2(int a,int b)
    23. {
    24. ...
    25. }

    auto型变量

    一般情况下,在函数内或者复合语句内定义的变量,就是auto型变量

    static型变量

    static既能定义局部变量又能定义全局变量,那static修饰的静态局部变量和auto修饰的自动变量有何区别?static修饰的静态全局变量和extern修饰的全局变量有何区别?

     

    静态局部变量

    自动变量
    生存期定义了该变量的源程序函数或复合语句内
    作用域函数内或复合语句中,其他函数不能使用
    赋初值若未赋初值,系统自动赋0;
    如果已赋初始值,则再次调用函数时,就不会执行赋初始值的语句
    若未赋初值,系统赋随机数;
    如果已赋初始值,则再次调用函数时,还会重复执行赋初始值的语句
    变量的值一次调用函数完成后,变量的值会被保留,再次调用,还是原来的值一次函数调用完成后,变量会被销毁,再次调用需要重新赋初始值
    程序运行结果1 2 3 4 51 1 1 1 1

     

     

     

     

     

     

     

     

     

     

    1. //定义静态局部变量
    2. #include
    3. int main()
    4. {
    5. int i;
    6. void fun();
    7. for(i=1;i<=5;i++)
    8. fun(); //函数调用
    9. return 0;
    10. }
    11. void fun()
    12. {
    13. static int j=0;
    14. j++;
    15. printf("%d ",j);
    16. }
    17. //定义自动变量
    18. #include
    19. int main()
    20. {
    21. int i;
    22. void fun();
    23. for(i=1;i<=5;i++)
    24. fun(); //函数调用
    25. return 0;
    26. }
    27. void fun()
    28. {
    29. auto int j=0;
    30. j++;
    31. printf("%d ",j);
    32. }
     

    静态全局变量

    全局变量
    生存期定义了该变量的源文件整个源文件
    作用域在定义了该变量的源文件内有效同一源程序的所有源文件都有效

     

     

     

     

    1. //假设一个源程序由源文件test_1和test_2组成
    2. //test_1.c
    3. int a,b; //定义全局变量
    4. static char ch;//定义静态全局变量
    5. int main()
    6. {
    7. ...
    8. }
    9. //test_2
    10. extern int a,b;//正确a,b是全局变量
    11. extern char ch;//错误,ch是静态全局变量
    12. fun()
    13. {
    14. ...
    15. }

    写在最后

    👍🏻点赞,你的认可是我创作的动力!

    ⭐收藏,你的青睐是我努力的方向!

    ✏️评论,你的意见是我进步的财富!

     

  • 相关阅读:
    C Primer Plus(6) 中文版 第1章 初识C语言 1.8 编程机制 1.11 本章小结
    Oracle-expdp方式升级19c问题合集
    一次XGBoost性能优化-超线程影响运算速度
    消息中间的应用场景
    Python中的元组
    OpenCV图像处理学习十四,图像阈值处理操作threshold()以及全局阈值和自适应阈值处理应用
    ”杠铃“策略:关于市场的一点思考,从转债到股票量化投研
    分析逆向案例九——奥鹏教育教师登录密码加密
    centos7.4启动卡在7的界面
    ChatGPT基础使用总结
  • 原文地址:https://blog.csdn.net/m0_73222051/article/details/128199455