当前位置: 首页 > news >正文

C语言中Definition与Declaration的区别及示例解析

C语言教材当中存在着关于定义以及声明的混淆情况,这直接致使了半数以上的C程序员写出过潜在的bug,仅需一个简单的规则便能厘清一所有的混乱,然而偏偏众多教材自身却都讲不明白,甚至在同一本书籍里还会存在前后矛盾的状况。

定义是分配内存的动作

定义乃是使得编译器切实向变量或者函数分配存储空间的那一步骤,举例来说,在源文件之中书写int iArray; ,编译器会即刻于内存里划分出400个字节以供这个数组使用,此动作仅仅能够出现一回,缘由在于内存无法重复分配给同一个实体,要是在多个文件里都书写了定义,链接器就会给出报错,表明重复定义。

往往放置定义的位置是在函数外面,也就是于全局作用域那里,或者是函数内部的静态变量处。不管放置于何处,只要编译器察觉到定义,便会生成与之对应的内存分配指令。对于数组而言,在定义的时候一定要给出清晰明确的长度,这是由于编译器需要知晓要分配多少空间。而这就是定义的核心特征。

声明是引用已有实体的方式

声明具备这样的功能,即向编译器传达某个名字已然存在,你仅是要对其加以使用,并非去创造它。举例来说时,在文件B当中书写extern int iArray;,如此一来编译器便会知晓这个数组在其他地方已经被定义妥当,无需再度开展空间分配的操作。声明能够出现不计其数的次数,只要是在同一个作用域范畴内进行重复声明,同样不存在问题。

那声明能够省略数组长度,缘由在于它无需分配内存。编译器仅关注类型信息,借此检查你运用这个数组的方式是否无误。示例而言,你写下iArray[0] = 5,编译器需知晓iArray是一个int数组,如此方可计算偏移量。至于数组确切有多少个元素,那是于定义之际确定之事。

结构类型声明不产生实体

声明了一种结构类型的struct veg { int weight, price_per_lb; },这一行仅仅是界定了一个类型模板,并不会产生任何能够执行的代码。编译器只是将这个结构所包含的成员记录下来,每个成员的类型是怎样的,以及整个结构占据多少字节。这些信息被应用于后续定义结构变量时的内存分配。

运转期间,操作系统于加载程序之时不会针对这个结构类型去分配任何的内存空间。唯有在运用这个类型界定了变量,像是struct veg onion;这般,编译器才会进而生产出分配空间的代码。结构类型的声明从根本上来说是一种元数据,其存于编译器的符号表里面,用以去引导后续的变量定义。

结构变量定义才是真分配

写下struct veg onion, radish, turnip;这行代码之际,编译器方才着手分配实际的内存空间。每个结构变量莫不占用sizeof(struct veg)大小的内存,此大小于编译之时便已确定。所分配的空间涵盖了结构内部全部成员变量所需的存储。

要是采用动态内存分配,举例来说像malloc(sizeof(struct veg)),那便是于运行之际从堆当中去申请空间。此处的sizeof运算符在编译之时就已计算得出结构的大小,这个大小信息正是源自之前的结构类型声明。要是没有那个声明,编译器压根就不清楚应当去分配多大的空间。

类型声明和变量定义可以合并

在C语言当中,你是能够将结构类型声明以及变量定义书写于同一行的,struct veg这是一种结构类型,其中包含int weight以及price_per_lb这些成员,onion、radish、turnip这则是依据该结构类型所定义的变量。这样的一种写法同时达成了两件事情,一件事情是声明了有一个称之为veg的结构类型,另一件事情是定义了三个属于该类型的变量。类型的名称veg在这儿是属于可选择的情况,如果将其省略掉,那么你便无法再去定义这个类型的其他变量了。

分开来进行书写的益处所在是其具备复用性,将结构类型声明放置于头文件之中,众多的源文件能够借助包含此头文件的方式去加以运用该类型,然而变量定义一般是应置于某一源文件内,其余的文件会运用extern声明来予以引用,这样的一种分离恰恰就是大范围项目组织代码的标准性做法。

类声明在C++里的对应关系

C++其中的类跟C语言的结构类型有种类似的状况,陈述一个类并不会去分配内存,class Vegetable { int weight; int price; };这一行代码仅仅是定义了一种类类型,告知编译器这个类的成员变量以及成员函数是怎样的情形,代码进行加载的时候,操作系统不会为这种样式的类本身分配任何的空间。

倘若你借由这个类去创建对象,就像Vegetable onion ;这样,编译器方才会去分配内存。要是运用new Vegetable(),那是于堆上进行动态分配的操作。在C++里,类的声明与对象的定义被划分得极为清晰,类的定义属于类型定义范畴,并不占用运行时的内存空间,唯有实例化出来的对象才会占用空间。

将定义跟声明两者有所区别清晰弄明白掌握住,如此写出那种代码才能够防止避免链接错误以及未定义行为出现。你所编写的程序里头,是否存在因把定义跟声明混淆搞错而折腾耗费一整个晚上时间的情况呢?欢迎于评论区域分享你遭遇踩坑的经历情况哦。

http://www.jsqmd.com/news/531894/

相关文章:

  • ROS机械臂开发必看:MoveIt!配置与OMPL运动规划全解析
  • 软件测试方法论:深度学习模型的质量保障体系构建
  • 2026车库门优质品牌推荐榜:车库门价格、车库门厂家推荐、铝合金卷帘门、防火卷帘门、防火车库门、不锈钢卷帘门、不锈钢车库门选择指南 - 优质品牌商家
  • Builder.io终极指南:5个技巧掌握可视化拖拽式无头CMS开发
  • MiroFish预测引擎:智能模拟技术驱动的平行世界构建与应用指南
  • FPGA实战:用ZYNQ PL端IO口驱动HDMI显示(附完整工程文件)
  • 神经符号推理实战:如何用ABL-Refl框架提升医疗诊断准确率(附Python代码)
  • fsdbreport参数全解析:从基础到高级用法,手把手教你生成精准报告
  • 保姆级教程:给AnythingLLM装上SearXNG的“联网大脑”,手把手配置Web Search(附公开API)
  • 微服务架构下的分布式事务一致性:基于Seata的完整解决方案
  • 终极指南:如何用Chartbuilder快速创建专业级数据可视化图表
  • 开源Sun-Panel vs 主流导航插件:自建导航页在数据安全和定制化上到底香不香?
  • 用STM32F103C8T6的ADC测12V锂电池电压,手把手教你设计分压电路和代码(标准库)
  • 如何构建你的AI硬件伙伴:3个关键步骤实现智能语音交互
  • 2026年益生菌饮料源头厂家优质合作指南:乳酸菌饮料工厂/乳酸菌饮料源头工厂/山东青岛饮乐多/活性乳酸菌饮料公司/选择指南 - 优质品牌商家
  • Selenium自动化进阶:用Python脚本自动检测Chrome版本并下载匹配的ChromeDriver
  • 别再用Django了!用Flask + Jinja2 + SQLAlchemy 10分钟搞定你的第一个Python Web应用
  • 2026护坡塑钢模板优质厂家推荐指南:现浇水沟塑钢模板/箱涵塑料模板/隧道电缆沟塑料模板/ABS塑钢模板厂家/人字骨架塑料模板/选择指南 - 优质品牌商家
  • LFM2.5-1.2B-Thinking-GGUF参数详解:max_tokens/temperature/top_p调优手册
  • 408考研必看:哈夫曼编码加权平均长度计算实战(附C语言完整代码)
  • 精细化阿里巴巴运营,不妨了解这些AI辅助服务,阿里资深运营/阿里巴巴运营/阿里运营,阿里巴巴运营达人分析 - 品牌推荐师
  • OpenAI Structured Outputs实战避坑:从健康记录到任务管理,我的3个复杂Schema设计翻车实录
  • 2026军事模型定做厂家专业推荐榜:火箭模型租赁/一比一仿真军事模型厂家/一比一军事模型厂家/做军事模型的厂家/选择指南 - 优质品牌商家
  • 如何用LibreHardwareMonitor实现专业硬件监控:从入门到精通
  • JLink-V8固件升级实战:解决Keil报错与克隆检测难题
  • NFS服务器搭建避坑指南:OpenEuler环境下的常见错误与解决方案
  • 华为eNSP实战:从零搭建WLAN网络(含完整配置命令+拓扑文件)
  • 手把手教你5步搞定汽车环视系统:从零到全景拼接实战指南
  • 如何突破NCM格式限制?3大方案实现音乐无缝流转
  • 基于EtherCAT与MQTT的工业运动控制系统设计