C编译器剖析_3.3 语法分析_C语言的外部声明(1)

C编译器剖析_3.3 语法分析_C语言的外部声明(2) 在上一小节中,我们讨论了C标准文法的“外部声明ExternalDeclaration”,介绍了“声明Declaration”和“函数定义FunctionDefintion”这两类外部声明,分别举了以下代码作为例子,在图3.3.4和图3.3.7中给出了这两者对应的语法树。 static  const  int  a1= 3, * a2, a3[5],a4(void);//声明Declarati 阅读详情

3.3  C语言的外部声明_ExternalDeclaration

    在分析完表达式和语句之后,《K&R》附录中关于标准C的6页文法,我们就已经差不多已经理解了一半,另外的3页文法基本上都是关于声明Declaration的,与声明相关的代码在ucl\decl.c中。不少编程语言的书籍中,对声明与定义是有严格区分的,在编译器遇到定义时,需要为之分配内存;而遇到声明时,则不必为之分配内存,因为该声明对应的内存可能已在其他地方进行过分配。例如,以下代码中,”extern int a;”被当作对变量a的声明;而”int b = 5;”则被当作定义,需要为变量b分配存储空间,并作相应初始化;”void f(void);”被当作对函数的声明,不需要占任何代码区空间;而函数g则是定义,需要在代码区中占用一片内存来存放函数代码。

         extern int a;

         int b = 5;

         void f(void);

         void g(void){

                   //…..

         }

     不过,从C标准文法的角度出发,上述“需要占内存的定义definition”或者“不占内存的声明”统统是被当作“外部声明”ExternalDeclaration来处理的。是否需要占内存,其实已经涉及“语义”。从C语言的语义出发,上述外部声明才有“是否要占内存”之分。换句话说,在语法分析阶段,我们暂时只在乎C程序在形式上是否符合C标准文法,我们在这个阶段只管“形”,而不管“含义”或“内容”。在语法分析阶段,一个预处理后的C文件就对应一个翻译单元TranslationUnit,它由若干个外部声明ExternalDeclaration构成,如图3.3.1第1415至1417行的产生式所示。

 

图3.3.1  ParseTranslationUnit()

     图3.3.1第1428行的函数调用ReadSourceFile()用于读入预处理后的C文件,第1430和1431行用于初始化当前读头的坐标位置,第1432行创建的向量TypedefNames用于存放通过typedef关键字命名的类型名,而接下来的OverloadNames则用于记录“另作他用”的typedef类型名,我们在3.1节时举例介绍过这两个向量的用法。第1435行创建了一个kind域为NK_TranslationUnit的语法树结点,对外部声明ExternalDeclaration的分析主要是通过第1450行的函数调用ParseExternalDeclaration()来实现的。而一个翻译单元是由若干个外部声明构成的,所以我们需要第1443行的while循环。引入第1446至1449行的代码,主要是为了允许形如”;”这样的空语句。第1436行、1450行和1451行的代码则用于把各个外部声明所对应的语法树结点链接到一起。执行到第1460行,我们就已经完成了对一个预处理后的C文件的语法分析工作,通过CloseSourceFile()关闭相关文件即可。图3.3.2给出了一个预处理后的C文件及其对应的语法树示意图。   

    

图3.3.2   翻译单元TranslationUnit对应的语法树

     图3.3.2中,我们通过在while()循环中调用函数ParseExternalDeclaration(),依次创建了kind域为NK_Declaration或NK_Function的4个语法树结点,其中NK_Function对应的是structastFunction结构体对象,描述了函数定义g的相关信息;而NK_Declaration对应的是structastDeclaration结构体对象,描述了变量声明a、变量定义b和函数声明f。而用于分析“外部声明”的相关代码如图3.3.3所示。

C编译器剖析_3.3 语法分析_C语言的外部声明(3) 在上一小节中,我们讨论了C标准文法中与声明Declaration有关的几个非终结符。在此基础上,接下来让我们看看ucl\decl.c中与“声明说明符DeclarationSpecifiers”和“声明符Declarator”相关的代码。函数ParseCommonHeader()分析了“声明说明符”和“声明符”, 图3.3.10 ParseCommonHeader()     图3. 阅读详情

相关推荐

C语言函数声明与定义:编译器视角的契约本质

函数声明是C语言分离编译模型中的核心契约机制,它在编译阶段提前约定函数接口(参数类型、数量、返回值),使编译器能静态校验调用合法性,避免运行时类型错配;函数定义则提供具体实现,二者共同支撑多文件项目的模块化构建。这种声明/定义分离的设计,直接决定了头文件(.h)与源文件(.c)的职责边界,并成为链接器解析符号依赖、解决undefined reference错误的前提。理解该机制,是掌握C语言工程化开发、VSCode多文件编译配置及Makefile构建演进的基础。

weixin_33738982的博客 1615

C编译器剖析_4.4 语义检查_外部声明_结构体和数组的初始化

本节讨论标量类型、数组、结构体和联合体的初始化。 在C语言中,全局或静态变量的初始化应为常量;而局部变量没有此要求。

SheIsC的专栏 1633

编程基础-外部声明在变量声明中的使用与原由

现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。创建一个工程,里面含有A.cpp和B.cpp两个简单的C++源文件:   //A.cpp   int i;

木头人在奋斗 612

C编译器剖析_5.1 中间代码生成及优化_简介

本节对UCC编译器的中间代码生成及优化进行简介,给出基本块BasicBlock、三地址码、控制流图CFG的相应数据结构,介绍有条件跳转、无条件跳转和间接跳转等概念。

SheIsC的专栏 4907

银河麒麟桌面版V10搭建Qt4.8.6开发环境

银河麒麟桌面版V10搭建Qt4.8.6开发环境

qq_34932364的博客 2399

Power BI财销一体分析——KPI分析应用实践

第九步:插入三个散点图,行拖入分销商表分销商字段,将度量值中的销量拖入X轴,将利润拖入Y轴,大小拖入度量值总销售额,将分销商表业务类型字段作为筛选条件添加给散点图,分别选择专业自行车店、增值经销商、仓库,使视觉对象固定显示不同业务类型的散点分布。这个公式其实是不需要我们自己写的,依赖于快度量值功能星级评分,基值选择度量值总销售额,星数选择5,最低星值评分选择0,最高星级评分值选择100,点击添加,星级评分度量值就建立好了,接下来我们理解一下公式。好的,今天的讲解就到这里。

BI瓶子的博客 1552

Jetson编译安装pycuda

可使用nvcc --version查看是否有信息输出,若没有,且安装cuda的情况下,需要手动将CUDA 的路径添加到环境变量中。编译生成_pvt_struct.cpython-38-aarch64-linux-gnu.so文件。基于jetson orin nano jetpack512模块上安装pycuda。4、获取pycuda源码(版本根据实际情况获取)2、进入conda环境并安装cuda工具包。9、若未检测出来需要清除并强制编译。7、编译成功后安装pycuda。5、配置编译并设置环境变量。

qq_48175141的博客 971

TensorFlow_PyTorch实战:构建AI人工智能回归模型

回归分析是机器学习的核心任务之一,用于预测连续型目标变量(如房价、股票价格、用户留存时间等)。基础线性回归模型的数学原理与代码实现多项式回归模型的过拟合处理与正则化技巧自定义数据集加载与数据预处理流程动态图(PyTorch)与静态图(TensorFlow)的编程范式对比模型评估指标与可视化分析方法核心概念:对比两大框架的架构设计,解析回归模型核心组件数学原理:推导线性回归的假设函数、损失函数及优化算法算法实现:提供TensorFlow和PyTorch的完整代码示例项目实战。

AI天才研究院 1429

卡尔曼滤波五步拆解:用Excel手推姿态解算全过程

本文通过Excel手推演示,详细拆解了卡尔曼滤波在姿态解算中的五步核心流程。文章以融合陀螺仪与加速度计数据估算角度为例,从状态预测、协方差更新到增益计算,逐步展示如何将抽象的矩阵运算转化为可视化的表格计算,帮助读者直观理解滤波器的“预测-修正”机制,并为算法实现与参数调优提供清晰指导。

hhh00的博客 978

YOLOv5改进 | 多尺度特征提取 | 结合多样分支块及融合的高级设计(CVPR2021)

YOLOv5改进 | 多尺度特征提取 | 结合多样分支块及融合的高级设计(CVPR2021)

qq_44224801的博客 2068

在 ABAP 环境中构建自定义健康监控指标:面向 SAP Cloud ALM 与 SAP Focused Run 的完整实践

本文介绍了在ABAP环境中开发自定义健康监控指标的方法。主要内容包括:1)标准监控指标的不足,如无法反映业务应用层面的问题;2)自定义监控架构,通过metric provider定义指标,由采集作业周期性获取数据并存储;3)核心实现技术,包括IF_GSM_API_PROVIDER接口和三个关键方法;4)指标从ABAP推送到SAP Cloud ALM/Focused Run的完整流程;5)开发实践步骤,从业务分析到具体实现。该方案可帮助团队监控业务关键指标,提升系统运维能力。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 262

新系统申请软件著作权详细操作说明

今年八月底版权中心系统升级,新系统相对好用一些,至少不用再拿IE访问了,但是多了一项实名认证。下面介绍新系统的操作流程。 目录注册、登录和实名认证注册登录实名认证软件登记申请申请表填写鉴别材料身份证明文件权利归属证明文件其他材料提交材料变更登记 注册、登录和实名认证 首先访问版权中心系统:https://register.ccopyright.com.cn/login.html,如果老系统有账号直接登录即可,没有的话需要注册。 注册 点击注册按钮进入注册。 根据实际情况选择个人或单位,每个个人或单位只能在

Programming Talk 1万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: C编译器剖析_3.2 语法分析_C语言的语句
下一篇: C编译器剖析_3.3 语法分析_C语言的外部声明(2)
SheIsC
博客等级 码龄12年 224粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值