前言
这是一道代码压缩题。与传统的算法竞赛题目不同的是,这道题目将额外给出一些语言的标准代码实现,你只需要专注于在尽可能缩短代码长度的同时,保证满足题目约束的输入数据相同时输出不会发生变化即可。我们给本题目提供的 C++ 代码在 5K 左右,另外还提供 C、java、python 的对应实现,这些代码可以通过附加文件一栏下载压缩包。你可以直接提交标准代码并获得基础分数,但如果你的目标是获得这道题的最高分数,在时间充足的情况下还是建议你能够仔细阅读题目描述和标准代码实现,确保自己能够充分理解题目的要求和代码的含义,在这之后再开始你的代码压缩之旅。祝你好运。
题目背景
在 C++ 等高级语言中,除了 int 和 float 等基本类型外,通常还可以自定义结构体类型。在本题当中,你需要模拟一种类似 C++ 的高级语言的结构体定义方式,并计算出相应的内存占用等信息。
题目描述
在这种语言中,基本类型共有 4 种: byte , short , int , long ,分别占据 1,2,4,8 字节的空间。
定义一个结构体类型时,需要给出类型名和成员,其中每个成员需要按顺序给出类型和名称。类型可以为基本类型,也可以为先前定义过的结构体类型。注意,定义结构体类型时不会定义具体元素,即不占用内存。
定义一个元素时,需要给出元素的类型和名称。元素将按照以下规则占据内存:
- 元素内的所有成员将按照定义时给出的顺序在内存中排布,对于类型为结构体的成员同理。
- 为了保证内存访问的效率,元素的地址占用需要满足对齐规则,即任何类型的大小和该类型元素在内存中的起始地址均应对齐到该类型对齐要求的整数倍。具体而言:
- 对于基本类型:对齐要求等于其占据空间大小,如
int 类型需要对齐到 4 字节,其余同理。
- 对于结构体类型:对齐要求等于其成员的对齐要求的最大值,如一个含有
int 和 short 的结构体类型需要对齐到 4 字节。
以下是一个例子(以 C++ 语言的格式书写):
struct d {
short a;
int b;
short c;
};
d e;
该代码定义了结构体类型 d 与元素 e。元素 e 包含三个成员 e.a, e.b, e.c,分别占据第 0∼1 , 4∼7 , 8∼9 字节的地址。由于类型 d 需要对齐到 4 字节,因此 e 占据了第 0∼11 字节的地址,大小为 12 字节。
你需要处理 n 次操作,每次操作为以下四种之一:
- 定义一个结构体类型。具体而言,给定正整数 k 与字符串 s,t1,n1,…,tk,nk ,其中 k 表示该类型的成员数量, s 表示该类型的类型名, t1,t2,…,tk 按顺序分别表示每个成员的类型, n1,n2,…,nk 按顺序分别表示每个成员的名称。你需要输出该结构体类型的大小和对齐要求,用一个空格分隔。
- 定义一个元素,具体而言,给定字符串 t,n 分别表示该元素的类型与名称。所有被定义的元素将按顺序,从内存地址为 0 开始依次排开,并需要满足地址对齐规则。你需要输出新定义的元素的起始地址。
- 访问某个元素。具体而言,给定字符串 s ,表示所访问的元素。与 C++ 等语言相同,采用
. 来访问结构体类型的成员。如 a.b.c ,表示 a 是一个已定义的元素,它是一个结构体类型,有一个名称为 b 的成员,它也是一个结构体类型,有一个名称为 c 的成员。你需要输出如上被访问的最内层元素的起始地址。
- 访问某个内存地址。具体而言,给定非负整数 addr ,表示所访问的地址,你需要判断是否存在一个基本类型的元素占据了该地址。若是,则按操作 3 中的访问元素格式输出该元素;否则输出
ERR 。
对于结构体类型的对齐要求和大小,形式化的定义方式如下:
- 设该结构体内有 k 个成员,其大小分别为 s1,…,sk ,对齐要求分别为 a1,…,ak ;
- 则该结构体的对齐要求为 a=max{a1,…,ak} ;
- 再设这些成员排布时的地址偏移量分别为 o1,…,ok ,则:
- o1=0 ;
- 对于 i=2,…,k , oi 为满足 oi−1+si−1≤oi 且 ai 整除 oi 的最小值;
- 则该结构体的大小 s 为满足 ok+sk≤s 且 a 整除 s 的最小值;
对于定义元素时的内存排布,形式化的定义方式如下:
- 设第 i 个被定义的元素大小为 si ,对齐要求为 ai ,起始地址为 bi ;
- 则 b1=0 ,对于 2≤i , bi 为满足 bi−1+si−1≤bi 且 ai 整除 bi 的最小值。