10-20-2021, 07:52 PM
看到一个搞笑的帖子:https://www.mysmth.net/nForum/#!article/CPlusPlus/419878
这个代码用一个大型switch-case来输出答案,结果某编译器编译时堆空间不足。我想实测一下现在的编译器能不能对付这种代码,于是我试着生成了C++,C,Ada,Zig四种语言的版本。
最后结果可以看原帖下方的评论。编译这些代码都不开优化选项。tcc对付这样的代码毫无压力,1s之内能编译出来。Clang编译C的版本用了10多秒,编译C++版本用了2分半钟。GCC编译这样的代码性能就不行了,C,C++,Ada都是好几分钟都不出代码,不知道卡在哪里。Zig编译时卡在语义分析阶段。
这个代码用一个大型switch-case来输出答案,结果某编译器编译时堆空间不足。我想实测一下现在的编译器能不能对付这种代码,于是我试着生成了C++,C,Ada,Zig四种语言的版本。
代码:
#!/usr/bin/env python
def print1(s):
print(' {}'.format(s))
def print2(s):
print(' {}'.format(s))
def putline_cxx(s):
return "cout << \"{}\" << endl;".format(s)
def putline_c(s):
return "puts(\"{}\");".format(s)
def case_start_c(s):
return "case {}:".format(s)
def case_end_c():
return "break;"
def putline_ada(s):
return "Put_Line(\"{}\");".format(s)
def case_start_ada(s):
return "when {} =>".format(s)
def case_end_ada():
return ""
def putline_zig(s):
return "try stdout.writeAll(\"%(str)s\\n\");" % {"str":s}
def case_start_zig(s):
return "%(str)s => {" % {"str":s}
def case_end_zig():
return "},"
def gencode(n, putline_code, case_start, case_end):
posname = ["个", "十", "百", "千", "万"]
sn = str(n)
print1(case_start(sn))
print2(putline_code("是{}位数".format(len(sn))))
t = n
idx = 0
while t > 0:
print2(putline_code("{}位数是:{}".format(posname[idx], t % 10)))
t = t // 10
idx = idx + 1
print2(putline_code("倒过来是:{}".format("".join([sn[i] for i in range(len(sn)-1,-1,-1)]))))
print2(case_end())
def gencode_cxx(upper_bound):
print('''#include <iostream>
using namespace std;
int main()
{
int x;
cin >> x;
switch(x) {
''')
for i in range(1, upper_bound):
gencode(i, putline_cxx, case_start_c, case_end_c)
print('''
}
}
''')
def gencode_c(upper_bound):
print('''#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
switch(x) {
''')
for i in range(1, upper_bound):
gencode(i, putline_c, case_start_c, case_end_c)
print('''
}
}
''')
def gencode_ada(upper_bound):
print('''with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Print_Number is
x: Integer;
begin
Get(x);
case x is
''')
for i in range(1, upper_bound):
gencode(i, putline_ada, case_start_ada, case_end_ada)
print('''
when others => null;
end case;
end Print_Number;
''')
# 1min for 1 .. 10000
def gencode_zig(upper_bound):
print(r'''const std = @import("std");
const stdin = std.io.getStdIn();
const stdout = std.io.getStdOut();
fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
var line = (try reader.readUntilDelimiterOrEof(
buffer,
'\n',
)) orelse return null;
// trim annoying windows-only carriage return character
if (std.builtin.os.tag == .windows) {
line = std.mem.trimRight(u8, line, "\r");
}
return line;
}
pub fn main() !void {
var buffer: [100]u8 = undefined;
const input = (try nextLine(stdin.reader(), &buffer)).?;
const x = std.fmt.parseInt(i32, input, 0) catch 0;
switch (x) {
''')
for i in range(1, upper_bound):
gencode(i, putline_zig, case_start_zig, case_end_zig)
print('''
else => {}
}
}
''')
if __name__ == "__main__":
gencode_c(100000)
最后结果可以看原帖下方的评论。编译这些代码都不开优化选项。tcc对付这样的代码毫无压力,1s之内能编译出来。Clang编译C的版本用了10多秒,编译C++版本用了2分半钟。GCC编译这样的代码性能就不行了,C,C++,Ada都是好几分钟都不出代码,不知道卡在哪里。Zig编译时卡在语义分析阶段。