【C语言】5.C语言函数(2)

文章目录

  • 7.嵌套调⽤和链式访问
    • 7.1 嵌套调⽤
    • 7.2 链式访问
  • 8.函数的声明和定义
    • 8.1 单个⽂件
    • 8.2 多个⽂件
    • 8.3 static 和 extern
      • 8.3.1 static 修饰局部变量
      • 8.3.2 static 修饰全局变量
      • 8.3.3 static 修饰函数


7.嵌套调⽤和链式访问

7.1 嵌套调⽤

嵌套调用就是函数之间的互相调用。

#include <stdio.h>void arr(){}void menu() {arr();
}int main() {menu();return 0;
}

这里 main 函数调用 menu函数。menu 函数调用 arr 函数。

函数可以嵌套调用,但是不能嵌套定义。


7.2 链式访问

所谓链式访问就是将一个函数的返回值作为另外一个函数的参数,像链条一样将函数串起来就是函数的链式访问。

#include <stdio.h>
int main()
{printf("%d\n", strlen("abcdef"));//链式访问 return 0;
}

把strlen的返回值直接作为printf函数的参数,链式访问 。

这个代码执行的结果是什么?

#include <stdio.h>
int main()
{printf("%d", printf("%d", printf("%d", 43)));return 0;
}

打印:

4321 

printf 函数的返回int printf ( const char * format, ... );,也就是说printf函数返回的是打印在屏幕上的字符的个数。

printf("%d", 43)这个打印43,在屏幕上打印2个字符,再返回2。

然后printf("%d", printf("%d", 43))打印2,在屏幕上打印1个字符,再返回1。

printf("%d", printf("%d", printf("%d", 43)));打印1。

所以屏幕上最终打印:4321


8.函数的声明和定义

8.1 单个⽂件

C语言编译器对源代码进行编译的时候,从第一行往下扫描的,所以函数调用之前先声明一下调用的函数。

#include <stdio.h>void menu() {}int main() {menu();return 0;
}

3-5行是函数menu的定义,第8行是函数的调用。

#include <stdio.h>int main() {menu();return 0;
}void menu() {}

如果把函数定义放在函数调用的后面就会报错。

#include <stdio.h>void menu();int main() {menu();return 0;
}void menu() {}

这里的函数定义放在了函数调用的后面,但是第3行是函数声明,所以就不会报错。

函数的调用一定要满足,先声明后使用;

函数的定义也是一种特殊的声明,所以如果函数定义放在调用之前也是可以的。


8.2 多个⽂件

一般在企业中我们写代码时候,代码可能比较多,不会将所有的代码都放在一个文件中;我们往往会根据程序的功能,将代码拆分放在多个文件中。

一般情况下,函数的声明、类型的声明放在头文件(.h)中,函数的实现是放在源文件(.c)文件中。

add.c

//函数的定义
int Add(int x, int y)
{return x+y;
}

add.h

//函数的声明
int Add(int x, int y);

test.c

#include <stdio.h>
#include "add.h"
int main()
{int a = 10;int b = 20;//函数调用int c = Add(a, b);printf("%d\n", c);return 0;
}

运行结果:

在这里插入图片描述


8.3 static 和 extern

作用域和生命周期:

作用域是限定这个名字的可用性的代码范围。

  1. 局部变量的作用域是变量所在的局部范围。

  2. 全局变量的作用域是整个工程(项目)。

生命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段。

  1. 局部变量的生命周期是:进入作用域变量创建,生命周期开始,出作用域生命周期结束。

  2. 全局变量的生命周期是:整个程序的生命周期。


static 和 extern 都是C语言中的关键字:

static 是 静态的 的意思,可以用来:

  • 修饰局部变量

  • 修饰全局变量

  • 修饰函数

extern 是用来声明外部符号的。


8.3.1 static 修饰局部变量

#include <stdio.h>
void test()
{//static修饰局部变量static int i = 0;i++;printf("%d ", i);
}
int main()
{int i = 0;for(i=0; i<5; i++){test();}return 0;
}

打印:

1 2 3 4 5 

如果把第五行的static去掉的话,就会打印:1 1 1 1 1

我们从输出结果来看,i的值有累加的效果,这是因为 static修饰局部变量改变了变量的生命周期。

生命周期改变的本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,但是被 static 修饰后存储到了静态区。存储在静态区的变量和全局变量是一样的,生命周期就和程序的生命周期一样了,只有程序结束,变量才销毁,内存才回收。但是作用域不变的。

使用建议:未来一个变量出了函数后,我们还想保留值,等下次进入函数继续使用,就可以使用static修饰。


8.3.2 static 修饰全局变量

代码1:

add.c

int g_val = 2018;

test.c

#include <stdio.h>
extern int g_val;
int main(){printf("%d\n", g_val);return 0;
}

代码2:

add.c

static int g_val = 2018;

test.c

#include <stdio.h>
extern int g_val;
int main(){printf("%d\n", g_val);return 0;
}

extern 是用来声明外部符号的,如果一个全局的符号在A文件中定义的,在B文件中想使用,就可以使用 extern 进行声明,然后使用。

结果:代码1正常,代码2在编译的时候会出现链接性错误。

解释:

一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。

本质原因是全局变量默认是具有外部链接属性的,在外部的文件中想使用,只要适当的声明就可以使用;但是全局变量被 static 修饰之后,外部链接属性就变成了内部链接属性,只能在自己所在的源文件内部使用了。

使用建议:如果一个全局变量,只想在所在的源文件内部使用,不想被其他文件发现,就可以使用static修饰。


8.3.3 static 修饰函数

代码1:

add.c

int Add(int x, int y)
{return x+y;
}

test.c

#include <stdio.h>
extern int Add(int x, int y);
int main()
{printf("%d\n", Add(2, 3));return 0;
}

代码2:

add.c

static int Add(int x, int y)
{return x+y;
}

test.c

#include <stdio.h>
extern int Add(int x, int y);
int main()
{printf("%d\n", Add(2, 3));return 0;
}

结果:代码1是能够正常运行的,但是代码2就出现了链接错误。

解释:

static 修饰函数和 static 修饰全局变量是一模一样的,一个函数在整个工程都可以使用,被static修饰后,只能在本文件内部使用,其他文件无法正常的链接使用了。

本质是因为函数默认是具有外部链接属性,具有外部链接属性,使得函数在整个工程中只要适当的声明就可以被使用。但是被 static 修饰后变成了内部链接属性,使得函数只能在自己所在源文件内部使用。

使用建议:一个函数只想在所在的源文件内部使用,不想被其他源文件使用,就可以使用 static 修饰。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/13081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker安装Mosquitto

在物联网项目中&#xff0c;我们经常用到MQTT协议&#xff0c;用MQTT协议做交互就需要部署一个MQTT服务&#xff0c;而mosquitto是一个常用的MQTT应用服务&#xff0c; Mosquitto是一个实现了消息推送协议MQTT v3.1的开源消息代理软件。MQTT&#xff08;Message Queuing Teleme…

python的几个关于文本文件的demo脚本

部分来自WeTab AI PRO 1.在文末添加一行文字 def add_endline(filename, texts): # 文本末尾增加一行with open(filename, a) as file:file.write(f\n{texts})file.close() 当使用 open() 函数打开文件时&#xff0c;第二个参数指定了文件的打开模式。常见的文件打开模式包…

【LeetCode】每日一题 2024_5_14 完成所有任务需要的最少轮数(哈希)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;完成所有任务需要的最少轮数题目描述代码与解题思路 每天进步一点点 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;完成所有任务需要的最少轮数 题…

拿到测试点如何跑

首先你要知道你测试点文件的位置,然后你要创建一个接收结果的文件,将你代码中的std::cin替换成infile,std::cout替换成outfile即可 #include <fstream> int main() {// 打开输入文件std::ifstream infile("C:\\Users\\Downloads\\P4779_1.in");// 打开输出文件…

OpenCV 图像退化与增强

退化 滤波 img_averagingcv2.blur(img2,(3,3)) #均值滤波 img_median cv2.medianBlur(img2,3) #中值滤波高斯模糊 result cv2.GaussianBlur(source, (11,11), 0)高斯噪声 def add_noise_Guass(img, mean0, var0.01): # 添加高斯噪声img np.array(img / 255, dtypefloat…

麒麟 V10 安装docker2

1. 查看系统版本 2.安装docker-ce 添加源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 安装docker yum install docker-ce --allowerasing 重启docker systemctl start docker 3.安装nvidia-container-runtime 添…

el-tooltip 提示框样式修改?

【element-plus el-tooltip官网地址&#xff1a; Tooltip 文字提示 | Element Plus】 <el-tooltippopper-class"Tooltip":content"content"placement"top"effect"light" ><span class"content">{{ content }}&l…

【TypeScript的JSX简介以及使用方法】

TypeScript 是 JavaScript 的一个超集&#xff0c;它添加了静态类型检查和面向对象编程的特性。JSX 是一种 JavaScript 的语法扩展&#xff0c;主要用于 React 组件的声明性渲染。TypeScript 完美地支持 JSX&#xff0c;并允许你为 React 组件和它们的 props 添加类型注解。 T…

C中Mysql的基本api接口

一、初始化参数返回值 二、链接服务器三、执行SQL语句注意事项 四、获取结果集4.1mysql_affected_rows和mysql_num_rows4.2mysql_store_result与mysql_free_result注意事项注意事项整体的工作流程 4.3mysql_use_result&#xff08;&#xff09;4.4mysql_field_count&#xff08…

001 侧边栏 地址增删改查 默认地址代码没完善

文章目录 user_index.htmlmyaccount_style.cssmyaccount_scripts.jsaddress_edit.htmlReceiverAddressReceiverAddressControllerReceiverAddressServiceImplIReceiverAddressServiceRFshopAppApplicationServletInitializerpom.xmlReceiverAddressMapper.xmlReceiverAddressMa…

文件存储解决方案-阿里云OSS

文章目录 1.菜单分级显示问题1.问题引出1.苹果灯&#xff0c;放到节能灯下面也就是id大于1272.查看菜单&#xff0c;并没有出现苹果灯3.放到灯具下面id42&#xff0c;就可以显示 2.问题分析和解决1.判断可能出现问题的位置2.找到递归返回树形菜单数据的位置3.这里出现问题的原因…

Golang 的 unmarshal 踩坑指南

文章目录 1. 写在最前面2. 字段区分出空字段还是未设置字段2.1 问题描述2.2 解决 3. 字段支持多种类型 & 按需做不同类型处理3.1 问题描述3.2 解决 4. 碎碎念5. 参考资料 1. 写在最前面 笔者最近在实现将内部通知系统的数据定义转化为产品定义的对外提供的数据结构。 举例…

算法学习笔记(5.0)-基于比较的高效排序算法-归并排序

##时间复杂度O(nlogn) 目录 ##时间复杂度O(nlogn) ##递归实现归并排序 ##原理 ##图例 ##代码实现 ##非递归实现归并排序 ##释 #代码实现 ##递归实现归并排序 ##原理 是一种基于分治策略的基础排序算法。 1.划分阶段&#xff1a;通过不断递归地将数组从中点处分开&…

Java 开发 框架安全:Spring 命令执行漏洞.(CVE-2022-22965)

什么叫 Spring 框架. Spring 框架是一个用于构建企业级应用程序的开源框架。它提供了一种全面的编程和配置模型&#xff0c;可以简化应用程序的开发过程。Spring 框架的核心特性包括依赖注入&#xff08;Dependency Injection&#xff09;、面向切面编程&#xff08;Aspect-Or…

【SpringBoot笔记43】SpringBoot应用程序集成spring-boot-admin监控工具

这篇文章,主要介绍SpringBoot应用程序如何集成spring-boot-admin监控工具。 目录 一、spring-boot-admin监控工具 1.1、创建admin-client客户端 (1)引入依赖

DeepSpeed

文章目录 一、关于 DeepSpeed1、DeepSpeed 是什么2、深度学习训练和推理的极致速度和规模3、DeepSpeed 的四大创新支柱1&#xff09;DeepSpeed 训练2&#xff09;DeepSpeed 推理3&#xff09;DeepSpeed 压缩4&#xff09;DeepSpeed4Science 4、DeepSpeed 软件套件DeepSpeed 库推…

React 第二十七章 Hook useCallback

useCallback 是 React 提供的一个 Hook 函数&#xff0c;用于优化性能。它的作用是返回一个记忆化的函数&#xff0c;当依赖发生变化时&#xff0c;才会重新创建并返回新的函数。 在 React 中&#xff0c;当一个组件重新渲染时&#xff0c;所有的函数都会被重新创建。这可能会…

青少年软件编程(Python)等级考试试卷(五级)2024年3月

2024.03 电子学会 青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;五级&#xff09; 一、单选题 1.以下代码的输出结果是? ) nums list(range(100, 201)) print(nums[::10]) A.[100,110,120,130,140,150,160,170,180,190,200] B.[100,101,1…

QML笔记八

QML与C交互 QML中调用C功能、使用QML或者Quick中的C接口、使用C实现自定义的QML对象 注&#xff1a; 只有QObject的派生类才能与QML交互 QML引擎集成Qt元对象系统&#xff0c;QObject的派生子类的属性、方法、信号都可以在QML中访问 C类可以被注册为一个QML实例 C类可以被注册为…

【Web后端】请求头

1、简介 请求头&#xff08;Request Headers&#xff09;是在HTTP协议中&#xff0c;客户端&#xff08;如浏览器或应用程序&#xff09;向服务器发送请求时附带的元数据。包含了关于请求的额外信息&#xff0c;有助于客户端与服务器之间的有效通信。请求头中的信息可以让服务…