C语言进阶-2
1、多文件C语言项目
1.1、简单的C语言程序(项目)
只有一个C文件(a.c),编译的时候gcc a.c -o a,执行的时候./a
1.2、复杂的C语言程序(项目)
是由多个C文件构成的。例如一个项目中包含2个c文件(a.c, b.c),编译的时候 gcc a.c b.c -o ab,执行的时候 ./ab
在a.c和b.c中分别定义main函数,各自单独编译时没问题;但是两个文件作为一个项目来编译
gcc a.c b.c -o ab的时候,就会报错:multiple definition of `main',这是因为a.c和b.c这时候组成了一个程序,而一个程序必须有且只能有一个main函数。
1.3、为什么需要多文件项目
因为一个真正的C语言项目是很复杂的,包含很多个函数,写在一个文件中不利于查找、组织、识别,所以人为的将复杂项目中的很多函数,分成了一个一个的功能模块,然后分开放在不同的.c文件中,于是乎有了多文件项目。
所以,在b.c中定义的一个函数,很可能a.c中就会需要调用。你在任何一个文件中定义的任何一个函数,都有可能被其他任何一个文件中的函数来调用。但是大家最终都是被main函数调用的,有可能是直接调用,也可能是间接调用。
1.4、多文件项目中,跨文件调用函数
在调用函数前,要先声明该被调用函数的原型。只要在调用前声明了该函数,那么调用时就好像这个函数是定义在本文件中的函数一样。
注意:函数使用的三大要素:函数定义、函数声明、函数调用
1、如果没有定义,只有声明和调用:编译时会报连接错误。undefined reference to `func_in_a'
2、如果没有声明,只有定义和调用:编译时一般会报警告,极少数情况下不会报警告。但是最好加上声明。
3、如果没有调用,只有定义和声明:编译时一般会报警告(有一个函数没有使用),有时不会报警告。这时候程序执行不会出错,只是你白白的写了几个函数,而没有使用浪费掉了而已。
4、在一个程序中,不管是一个文件内,还是该程序的多个文件内,都不能出现函数名重复的情况,一旦重复,编译器就会报错。主要是因为编译器不知道你调用该函数时到底调用的是哪个函数,编译器在调用函数时是根据函数名来识别不同的函数的。
1.5、跨文件的变量引用
(1)在a.c中定义的全局变量,在a.c中可以使用,在b.c中不可以直接使用,编译时报错 error: ‘g_a’ undeclared (first use in this function)。
(2) 想在b.c中使用a.c中定义的全局变量,有一个间接的使用方式。在a.c中写一个函数,然后函数中使用a.c中定义的该全局变量,然后在b.c中先声明函数,再使用函数。即可达到在b.c中间接引用a.c中变量的目的。
(3)想在b.c中直接引用a.c中定义的全局变量g_a,则必须在b.c中引用前先声明g_a,如何声明变量? extern int g_a;
1.5.1、extern关键字
extern int g_a;
这句话是一个全局变量g_a的声明,这句话告诉编译器,我在外部(程序中不是本文件的另一个文件)某个地方定义了一个全局变量 int g_a,而且我现在要在这里引用它告诉你编译器一声,不用报错了。
1.5.2、注意
1、只在b.c中声明变量,但是别的文件中根本没定义这个变量,那么编译报错(连接错误)undefined reference to...
2、在a.c中定义了全局变量g_a,但是b.c中没有声明g_a,引用该变量会直接报错了,未定义。
3、在a.c中定义,在b.c中声明,a.c和b.c中都没有引用该变量,程序不会出错。只是白白的定义了一个变量没用,浪费了。
4、局部变量不能跨文件使用,为局部变量属于代码块作用域。他的作用域只有他定义的那个函数内部。
5、静态局部变量不能跨文件使用,因为其本质上还是个局部变量。
6、讨论跨文件使用问题,只用讨论全局变量和函数就可以了。
1.5.3、总结
不管是函数还是变量,都有定义、声明、引用三要素。其中,定义是创造这个变量或者数,声明是向编译器交代它的原型,引用是使用这个变量或函数。所以如果没有定义只有声明和引用,编译时一定会报错。undefined reference to `xxx'
在一个程序里面,一个函数可以定义一次,引用可以有无数次,声明可以有无数次。因为函数定义或者变量的定义实际上是创造了这个函数/变量,所以只能有一次。(多次创造同名的变量会造成变量名重复,冲突;多次创造同名的函数也会造成函数名重名冲突)。声明是告诉编译器变量/函数的原型,在每个引用了这个全局变量/函数的文件之前都要声明该变量/函数。
1.6、头文件的引入
1.6.1、为什么需要头文件
从之前可以看到,函数的声明是很重要的。当我们在一个庞大的项目中,有很多个源文件,每一个源文件中都有很多个函数,并且需要在各个文件中相互穿插引用函数。在没有头文件时,需要使用别的.c文件中定义的函数时,都要先在本文件中先去声明该函数的原型,否则编译器要叫。所以多了的话很麻烦,而靠头文件就可以解决函数的声明问题。
1.6.2、#include包含头文件时,用<>和""的区别
<>用来包含系统自带的头文件,系统自带指的是不是你写的,是编译器或者库函数或者操作系统提供的头文件。
""用来包含当前项目目录中的头文件,这些一般是我们自己写的。
1.6.3、防止重复包含头文件
#ifndef __A_H__
#define __A_H__
//
// C语言头文件中的声明
//
#endif
1.6.4、注意
写程序时,最好不要在头文件中定义变量。因为这时该头文件被多个源文件包含时,就会出现重复定义问题。全局变量的定义就应该放在某个源文件中,然后在别的源文件中使用前是extern声明。
相关文章:
C语言进阶-2
1、多文件C语言项目 1.1、简单的C语言程序(项目) 只有一个C文件(a.c),编译的时候gcc a.c -o a,执行的时候./a 1.2、复杂的C语言程序(项目) 是由多个C文件构成的。例如一个项目中包含2个c文件(…...
Zabbix监控之分布式部署
文章目录 Zabbix监控之分布式部署zabbix proxy概述部署zabbix-proxy节点规划基础环境准备安装proxy以及数据库配置数据库添加服务端host解析修改zabbix-proxy配置文件启动代理服务器 zabbix页面(1)在zabbix页面添加代理(2)zabbix-agent连接proxy Zabbix监控之分布式部署 zabbi…...
vue2企业级项目(七)
vue2企业级项目(七) 组件封装 src目录下创建components/index.js const components require.context("./modules", true, /index\.js$/);export default {install: (Vue) > {components.keys().forEach((key) > {let component compo…...
PDPS教程:导出带颜色的JT格式2D布局图文件的另一种方法
目录 概述 布局图平面化与边缘化处理 导出为JT格式文件 JT格式文件查看 概述 在PDPS软件中导入机器人生产线或工作站2D布局图之前,要先将布局图文件转换为JT格式。 使用Crossmanager软件转换出来的2D布局图文件会将图形元素原有的颜色自动修改为黑白颜色&…...
AI面试官:Asp.Net 中使用Log4Net (二)
AI面试官:Asp.Net 中使用Log4Net (二) 当面试涉及到使用log4net日志记录框架的相关问题时,通常会聚焦在如何在.NET或.NET Core应用程序中集成和使用log4net。以下是一些关于log4net的面试题目,以及相应的解答、案例和代码: 文章目…...
C# Solidworks二次开发:向量相关的数学函数API的使用介绍
今天要讲的是Solidworks二次开发时候,如何使用一些与数学相关的API方法的介绍,在Solidworks中本身提供了一个函数用于对数学对象的访问,函数名为MathUtility。借助这个函数,我们来引出今天要介绍的几个API。 (1&#…...
table 导出表格 Excel
在请求中需要设置 responseType: blob export const requestExport (api, method, params {}, config) > {const apiToken localStorage.getItem(token);const data method GET ? params : data;let headers {BackServer-Token: ${apiToken},};if (config?.headers…...
基于 Flink SQL CDC 数据处理的终极武器
文章目录 一、传统的数据同步方案与 Flink SQL CDC 解决方案1.1 Flink SQL CDC 数据同步与原理解析1.2 基于日志的 CDC 方案介绍1.3 选择 Flink 作为 ETL 工具 二、 基于 Flink SQL CDC 的数据同步方案实践2.1 CDC Streaming ETL2.2 Flink-CDC实践之mysql案例 来源互联网多篇文…...
uniapp使用HQChart的k线,用webSocket更新数据
项目:不借用HQChart的各种接口数据,即数据后端返回,但是数据格式要和原数据格式一样。 //k线图 CreateHQChartKLine(){var chartHeightuni.upx2px(this.ChartHeight);let hqchartCtrlthis.$refs.HQChartCtrl;hqchartCtrl.KLine.Option.Type&…...
idea的Plugins中搜索不到插件
1、ctrlalts 打开设置 ; 2、搜索框输入plugins; 3、点击plugins; 4、点齿轮按钮,选择HTTP Proxy settings; 如下操作: 5、刷新DNS,ipconfig /flushdns 6、重新打开idea 的plugins 插件列表出来了...
flask 实现简单的登录系统demo
你提供的代码是一个基本的Flask应用程序,实现了一个简单的登录系统。以下是代码的详细解释: 1. 导入必要的模块:os 用于生成密钥,Flask 用于创建Web应用程序。 2. 创建Flask应用程序的实例,并为会话管理设置一个密钥。…...
Spring Security安全配置
使用Spring Boot与Spring MVC进行Web开发时,如果项目引入spring-boot- starter-security依赖启动器,MVC Security 安全管理功能就会自动生效,其默认的安全配置是在SecurityAutoConfiguration和UserDetailsServiceAutoConfiguration中实现的。…...
2023Java后端开发之100道常见经典面试题
目录 1.重载和重写的区别? 2.String 和 StringBuffer、StringBuilder 的区别是什么? 3. 与 equals 的区别? 4.抽象类和接口的区别是什么? 5. 面向对象的特点 6.Collection 和 Collections 有什么区别? 7.List、Set、Map 之…...
Redis详解,包括安装命令,应用场景,优缺点,案列分析,各个开发语言如何应用
目录 1、安装命令2、应用场景3、优缺点4、案例分析5、各个开发语言如何应用? Redis 是一个基于内存的开源数据库系统,被广泛应用于 Web 应用、消息队列、缓存、实时统计等领域。下面是 Redis 的详解,包括安装命令、应用场景和优缺点ÿ…...
AI数字人:金融数字化转型的“关键先生”
今年年初ChatGPT的火热,在全球掀起一阵生成式AI(AIGC)热潮。国外的OpenAI、国内的百度等企业,都在AIGC上强力布局。 各种应用场景中,AIGC助力的数字人引起了市场注意。 事实上,数字人不是个新鲜事。早在1…...
mac关闭VPN之后,浏览器就不能够正常上网了(图解)
可能打开谷歌浏览器会显示无法正常连接网络等信息,这个时候可以按照以下步骤: 点击"检查代理服务器地址" 会显示以下这段话,按照这个步骤来操作就可以了。 打开系统偏好设置,点击网络 点击高级 取消掉所有已勾选代…...
YOLOv5改进系列(17)——更换IoU之MPDIoU(ELSEVIER 2023|超越WIoU、EIoU等|实测涨点)
【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制...
基于WSL2、Ubuntu和VS Code的CUDA平台运行C语言程序
一、CUDA程序执行方法 执行步骤为: 安装Visual Studio Code。在Visual Studio Code中安装插件WSL与电脑的WSL2进行连接。点击左下角,然后再选择连接到WSL。 在WSL中创建以 .cu 为后缀的文件。 rootDESKTOP-HR6VO5J:~# mkdir CUDA /…...
构建外卖系统小程序,订单管理功能实现步骤详解
外卖系统小程序是近年来越来越受欢迎的一种订餐方式,方便快捷,并且可以减少人与人之间的接触,更加卫生安全。为了搭建一个完善的外卖系统小程序,订单管理功能是必不可少的一部分。在本文中,我们将详细介绍如何实现订单…...
用asp.net开发h5网页版视频播放网站,类似优酷,jellyfin,emby
之前用jellyfin开源软件搞了一个视频播放服务器,用来共享给家里人看电影和电视剧,jellyfin虽然各方面功能都很强大,但是界面和使用习惯都很不适合,于是就想着利用下班休息时间做一套自己喜欢的视频网站出来. 本来是打算直接用jellyfin的源码进行修改,源码是用C# netcore 写的服…...
当知识有了‘关系网‘:LightRAG如何让大模型‘秒懂‘你的文档?
想象一下,你有一座藏书万卷的图书馆,但你找书的方式只有一种——记住每本书某个页面的关键词,然后靠"猜"来定位。 这,就是传统RAG系统的尴尬处境。 今天要介绍的这个开源项目LightRAG,被顶会EMNLP 2025接收…...
计算机毕业设计:Python汽车销售数据可视化与分析系统 Flask框架 requests爬虫 可视化 数据分析 大数据 机器学习 大模型(建议收藏)✅
博主介绍:✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌ > 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与…...
别再手写表单了!用Vue3+AI做个自己的低代码设计器,5分钟搞定一个页面
用Vue3AI打造个人专属低代码表单设计器:5分钟解放重复劳动 如果你是一名中后台开发者,每天被各种CRUD表单折磨得焦头烂额,这篇文章就是为你准备的。想象一下:当你接到第100个类似的用户管理表单需求时,不再需要从零开始…...
芯片研发的残酷真相:流片成功只是开始
芯片成功"点亮"那一刻,项目算完成了吗?如果你认为算,那大概率还没经历过真正的芯片项目后期。事实是,点亮和demo跑通,只不过是拿到了入场券而已。真正的战斗,从客户拿到样片那一刻才开始。很多工…...
深入理解 MySQL 事务:从基础到实战,一篇吃透
在开发和运维 MySQL 数据库的过程中,事务(Transaction) 是绕不开的核心知识点,它是保证数据库数据安全、一致、可靠的基石。无论是电商下单、银行转账、支付结算,还是日常的业务数据操作,都离不开事务的支撑…...
使用ZLMRTCClient.j实现webRtc流播放
1. 核心播放器组件封装 (WebRTCPlayer.vue)为了在项目中复用播放逻辑,我们首先封装一个 WebRTCPlayer 组件。该组件主要负责:初始化播放器实例:配置 ZLMRTCClient.Endpoint。处理自动播放:解决浏览器禁止带音频自动播放的问题。生…...
Python内存管理策略对比评测报告(2024权威版):仅1种策略通过了金融级SLA压力测试,其余4种已淘汰
第一章:Python智能体内存管理策略对比评测报告(2024权威版)概述Python智能体(如基于LLM的Agent框架、自主任务调度器、多步推理引擎)在运行过程中面临高频对象创建、长生命周期缓存、跨线程引用共享等复杂内存场景。传…...
忍者像素绘卷参数详解:描绘步数/幻化精度/画幅比例三维度效果对照表
忍者像素绘卷参数详解:描绘步数/幻化精度/画幅比例三维度效果对照表 1. 像素艺术创作新纪元 忍者像素绘卷是基于Z-Image-Turbo深度优化的图像生成工作站,它将传统漫画创作与16-Bit复古游戏美学完美融合。这款工具采用明亮的"云端"视觉设计&a…...
MCP 会不会成为 AI 系统的“新中间件”?
一、为什么人们开始把 MCP 和“中间件”类比?(Why Do People Start Comparing MCP to “Middleware”?)1、MCP 出现的位置非常“熟悉”(MCP Appears in a Very Familiar Position)当人们第一次在企业架构中引入 MCP 时…...
python异常模拟工具类(异常生成工具类)
文章目录创建代码类使用主要是做测试的时候方便,创建代码类 1、新建python文件exception_mock_utils.py,代码为: import random import time from typing import Any, Optionalclass ExceptionMockUtils:"""异常模拟工具类用…...
