这篇文章上次修改于 420 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
Brainfuck 语言是什么?
Brainfuck 的代码大概长这样:
++++++++++[>+++++++>++++++++++>+++>+++++++++>+<<<<<-]>++.>+.+++++++..+++.>++.>---.<<.+++.------.--------.>+.>>.
总之视觉效果很震撼。
Brainfuck 语言是一门极小的图灵完备语言。它只有八种有效字符:
操作符 | 作用 |
---|---|
> | 指针向右移一字节 |
< | 指针向左移一字节 |
+ | 当前指向字节的值加一 |
- | 当前指向字节的值减一 |
, | 请求一个输入,将其ASCII码存到当前指向字节 |
. | 将当前指向字节的值作为ASCII码输出一个字符 |
[ | 循环体开头,当前指向字节为0时退出循环 |
] | 循环体结尾 |
其他任何字符都视为注释。看到这里你应该能想象出这种代码会有多么折磨了。
在 macOS 上,若你有 Homebrew 环境,你可以用这条指令安装一个 Brainfuck 解释器:
$ brew install brainfuck
该解释器的实现来自于这个 GitHub 仓库。
例程入门
你可以想象一个指针指向一排格子,每个格子内的数字都要在0~255之间。最开始指针指向最左边第一个格子,当收到指令>
时,指针向右跑去第二个格子;再收到指令<
时,指针向左跑回第一个格子。
现在写一份代码:
++++++++++++++++++++++++++++++++++++++++++++++++.
在第一格里作连续48个+
,最后用一个.
将这个值对应的
ASCII 字符输出。这段代码的作用就是输出一个字符「0」,也就是 ASCII
码值为48的字符。
将代码文件保存成随便什么文件名,比如first_program.bf
。使用下面的命令把这个文件传给解释器就可以运行了:
$ brainfuck first_program.bf
输出如下:
0
顺带一提,「0」的后面连换行符都没有。如果你在用
bash,下一个命令提示符会直接跟在0后面;如果你和我一样在用
zsh,默认配置下会有一个莫名其妙的百分号%
跟在后面,并自动帮你换了一行。
如果你懒得为这种事写个文件,这个解释器支持你直接把代码在终端里作为参数传给它,用-e
关键字就好:
$ brainfuck -e "++++++++++++++++++++++++++++++++++++++++++++++++."
连续48个+
太不方便了,而且有可能数错。你刚才可能和我一样偷了个懒,只打了六个加号,然后复制粘贴直到总共八遍。这其实是个好思路,把48拆成6乘8来实现,就可以减少许多加号。换成
Brainfuck 来写就是把6加八遍,或者把8加六遍。我们用前者:
++++++++[>++++++<-]>.
解释一下这段代码:
++++++++
在第一格里放8;[
看一下当前格(第一格)归零了没有。如果没有,开始循环:>
右移到第二格;++++++
给第二格加上6;<
左移到第一格;-
给第一格减去1;
]
回到第2步;>
右移到第二格;.
把第二格里这个字符输出。也即输出 ASCII 码为48的字符,也就是「0」。
Brainfuck 会把其他文字都当注释,所以要是看不懂,你可以多写点注释多换些行。
来写 Hello World!
想想就很折磨,太棒了!
最简单的实现方式就是直接去查 ASCII
码表,然后在每一格里只用+
填好字,然后输出。
但那样就太多加号了。相比那种,这里有稍微高级一点的实现,加号的数量比较好看:
++++++++++ 10遍
[
>+++++++ 第二格:加7
>++++++++++ 第三格:加10
>+++ 第四格:加3
>+++++++++ 第五格:加9
>+ 第六格:加1
<<<<<- 循环条件,第一格:减1
] 循环完成,二~六格为:70,100,30,90,10
>++. 第二格:72,输出:H
>+. 第三格:101,输出:e
+++++++.. 第三格:108,输出两遍:ll
+++. 第三格:111,输出:o
>++. 第四格:32,输出空格
>---. 第五格:87,输出W
<<. 第三格:还是111,输出o
+++. 第三格:114,输出r
------. 第三格:108,输出l
--------. 第三格:100,输出d
>+. 第四格:33,输出!
>>. 第六格:10,换行
我贴心地加了注释。如果你只是想要吓人,可以去掉注释写在一行里:
++++++++++[>+++++++>++++++++++>+++>+++++++++>+<<<<<-]>++.>+.+++++++..+++.>++.>---.<<.+++.------.--------.>+.>>.
在 GitHub
仓库里有个更短的 Helloworld
官方例程brainfuck/examples/hello-short.bf
,套了一大堆循环,看起来很恐怖,如果有兴趣可以分析一下试试看。
另外这语言是可以写 Quine 程序的。毕竟它图灵完备,而且也能输出。太可怕了。