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

本文详细介绍了C编译器在处理结构体和数组初始化时的语义检查过程,涉及位运算、类型匹配、初始化检查及常量性验证。通过对初始化值的分析,展示了如何构建和检查struct initData链表,以及处理位域、数组、联合体和结构体初始化的特殊情况。
摘要由CSDN通过智能技术生成

4.4.3  结构体和数组的初始化

         在这一小节中,我们来讨论一下声明中的初始化。在不少程序设计语言的教材中,对变量的声明和定义是有严格区分的。但从C标准文法的角度来看,它们都是由非终结符Declaration产生的,因此对变量初始化的语义检查也在declchk.c中进行。我们先举一个例子来说明“我们在这一小节所处的起点和终点”,如图4.4.15所示。在图的左侧,我们给出初始化值{ {20},30}经语法分析后形成的语法树,这是我们本小节的起点;在图的右侧,由struct initData对象构成的链表则是我们对左侧语法树进行语义检查后构造的,dt.a在结构体对象dt中的偏移为0,而dt.c的偏移为8,因此图中offset为0的结点代表“我们需要把dt.a初始化为20”,而offset为8的结点代表“我们需要把dt.c初始化为30”,图中右侧的链表就是我们在本小节的终点。


图4.4.15 struct initData

         结构体中允许存在位域成员,其初始化就需要经过一些位运算,如图4.4.16第1至第8行注释中的代码所示,对于第7行的pte而言,其实际所占的内存为4字节,我们需要先把初值3左移12位后,再跟初值64进行或运算,然后用所得结果((3<<12)|64)来初始化pte对象。图4.4.16第27至45行的PlaceBitField函数实现了左移运算,对于常量,在编译时我们就可在第31至34行进行常量折叠,而对于不是常量的操作数,我们才需要在第35至43行生成一个进行左移运算的语法树结点。而图4.4.16第9至26行的BORBitField函数实现了按位或运算。


图4.4.16 BORBitField()

         接下来,我们来看一下对初值进行语义检查的函数CheckInitializer,如图4.4.17所示。图4.1.17第8至第18行的代码,用于处理形如第9行注释所示的数组初始化,“用字符串来初始化一维数组”是数组初始化的一个特例。图4.4.17第10行调用的CheckCharArrayInit函数用来处理一些非法的情况。 函数CheckCharArrayInit的代码相对简单,我们就不再展开,只在图4.4.17第12至14行注释中给出一些错误示例。而对于结构体或联合体对象而言,其初值也可以是同类型的其他

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值