1 条题解
-
0
思路与算法
给每个类型存大小、对齐和按定义顺序排列的成员偏移。新成员起点为不小于当前末尾且为其对齐倍数的最小值;类型大小最后按最大成员对齐取整。全局变量同样对齐连续分配。名称查询逐级沿成员路径累加偏移;地址查询先定位变量,再逐层找覆盖该偏移的成员,到基本类型才输出完整名称,找不到则ERR。
正确性说明
取整函数ceil(end/align)*align正是满足形式化对齐规则的最小地址,按成员与变量顺序归纳可知存储布局准确。路径访问的每一级偏移相加就是实际地址。各成员字节范围互不相交,地址查询至多属于一个成员;若落在间隙或尾部填充则不属于任何基本对象,输出ERR正确。下降到基本成员给唯一全路径。
复杂度
设F为总成员数、Q为操作数、H为最大嵌套深度、K为最大成员数。含布局和容器初始化,O(F+QHK)时间、O(F+Q)空间;路径字符串处理另按实际长度线性计。
易错点
结构体尾部也补齐,变量之间也有空隙;地址0合法。只有基本类型字节属于可输出名称。大小与地址达1e18,使用64位,内层成员名字可在不同类型重复。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; struct Field { string name; int type; long long offset; }; struct Type { long long size, align; vector<Field> f; }; long long alignUp(long long x, long long a) { return (x + a - 1) / a * a; } int main() { int n; cin >> n; vector<Type> types = {{1, 1, {}}, {2, 2, {}}, {4, 4, {}}, {8, 8, {}}}; map<string, int> bytype = {{"byte", 0}, {"short", 1}, {"int", 2}, {"long", 3}}; struct Var { long long base; int type; string name; }; vector<Var> vars; map<string, int> byvar; long long used = 0; while (n--) { int op; cin >> op; if (op == 1) { string name; int k; cin >> name >> k; Type t{0, 1, {}}; while (k--) { string ty, field; cin >> ty >> field; int id = bytype.at(ty); t.size = alignUp(t.size, types[id].align); t.f.push_back({field, id, t.size}); t.size += types[id].size; t.align = max(t.align, types[id].align); } t.size = alignUp(t.size, t.align); bytype[name] = types.size(); types.push_back(t); cout << t.size << " " << t.align << "\n"; } else if (op == 2) { string ty, name; cin >> ty >> name; int id = bytype.at(ty); used = alignUp(used, types[id].align); byvar[name] = vars.size(); vars.push_back({used, id, name}); cout << used << "\n"; used += types[id].size; } else if (op == 3) { string s; cin >> s; replace(s.begin(), s.end(), '.', ' '); istringstream in(s); string name; in >> name; Var v = vars[byvar.at(name)]; long long at = v.base; int type = v.type; while (in >> name) { for (auto f : types[type].f) if (f.name == name) { at += f.offset; type = f.type; break; } } cout << at << "\n"; } else { long long at; cin >> at; int v = -1; for (int i = 0; i < (int)vars.size(); i++) if (vars[i].base <= at && at < vars[i].base + types[vars[i].type].size) { v = i; break; } if (v < 0) { cout << "ERR\n"; continue; } long long rem = at - vars[v].base; int type = vars[v].type; string result = vars[v].name; bool ok = true; while (type >= 4) { bool found = false; for (auto f : types[type].f) if (f.offset <= rem && rem < f.offset + types[f.type].size) { rem -= f.offset; type = f.type; result += '.' + f.name; found = true; break; } if (!found) { ok = false; break; } } cout << (ok ? result : "ERR") << "\n"; } } }
- 1