很偶然的机会认识到这个语言,当时在纸上对着它的 "hello world" 程序一个字符一个字符的解释了一遍,惊讶于它的设计思想。到网上查了下,记录下来。
以下是正文 :
--------------------------------
Brainfuck,是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf***,甚至被简称为BF。
Müller的目标是创建一种简单的、可以用最小的编译器来实现的、符合图灵完全思想的编程语言。这种语言由八种运算符构成,为Amiga机器编写的编译器(第二版)只有240个字节大小。
就象它的名字所暗示的,brainfuck程序很难读懂。尽管如此,brainfuck图灵机一样可以完成任何计算任务。虽然brainfuck的计算方式如此与众不同,但它确实能够正确运行。
这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。
下面是这八种状态的描述,其中每个状态由一个字符标识:
字符 含义
> 指针加一
< 指针减一
+ 指针指向的字节的值加一
- 指针指向的字节的值减一
. 输出指针指向的单元内容(ASCII码)
, 输入内容到指针指向的单元(ASCII码)
[ 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处
] 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处
(按照更节省时间的简单说法,]也可以说成“向前跳转到对应的[状态”。这两解释是一样的。)
(第三种同价的说法,[意思是"向后跳转到对应的]",]意思是"向前跳转到对应的[指令的次一指令处,如果指针指向的字节非零。")
Brainfuck程序可以用下面的替换方法翻译成C语言(假设ptr是char*类型):
Brainfuck C
> ++ptr;
< --ptr;
+ ++*ptr;
- --*ptr;
. putchar(*ptr);
, *ptr =getchar();
[ while (*ptr) {
] }
(以上内容源自维基百科:http://zh.wikipedia.org/wiki/Brainfuck)
下面是它的一个解释器:
--------------------------------
#include <stdio.h>
int p, r, q;
char a[5000], f[5000], b, o, *s=f;
void interpret(char *c)
{
char *d;
r++;
while( *c ) {
//if(strchr("<>;+-,.[]\n",*c))printf("%c",*c);
switch(o=1,*c++) {
case '<': p--; break;
case '>': p++; break;
case '+': a[p]++; break;
case '-': a[p]--; break;
case '.': putchar(a[p]); fflush(stdout); break;
case ',': a[p]=getchar();fflush(stdout); break;
case '[':
for( b=1,d=c; b && *c; c++ )
b+=*c=='[', b-=*c==']';
if(!b) {
c[-1]=0;
while( a[p] )
interpret(d);
c[-1]=']';
break;
}
case ']':
puts("UNBALANCED BRACKETS"), exit(0);
case '#':
if(q>2)
printf("%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d\n%*s\n",
*a,a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],3*p+2,"^");
break;
default: o=0;
}
if( p<0 || p>100)
puts("RANGE ERROR"), exit(0);
}
r--;
// chkabort();
}
main(int argc,char *argv[])
{
FILE *z;
q=argc;
if(z=fopen(argv[1],"r")) {
while( (b=getc(z))>0 )
*s++=b;
*s=0;
interpret(f);
}
}
--------------------------------
代码比较直接,不做解释了。
一个 BF 的 hello world ( 注意,这里成行的减号是起分割线作用的,不是 BF 代码。)
--------------------------------
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
--------------------------------
解释
--------------------------------
+++ +++ +++ + initialize counter (cell #0) to 10
[ use loop to set the next four cells to 70/100/30/10
> +++ +++ + add 7 to cell #1
> +++ +++ +++ + add 10 to cell #2
> +++ add 3 to cell #3
> + add 1 to cell #4
<<< < - decrement counter (cell #0)
]
>++ . print 'H'
>+. print 'e'
+++ +++ +. print 'l'
. print 'l'
+++ . print 'o'
>++ . print ' '
<<+ +++ +++ +++ +++ ++. print 'W'
>. print 'o'
+++ . print 'r'
--- --- . print 'l'
--- --- --. print 'd'
>+. print '!'
>. print '\n'
--------------------------------
(以上内容来自 coolshell : http://coolshell.cn/articles/1142.html,作者: 陈皓)
在网上又查到了一个代码写得很好的解释器,代码如下:
--------------------------------
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define TOKENS "><+-.,[]"
#define CODE_SEGMENT_SIZE 30000
#define STACK_SEGMENT_SIZE 1000
#define DATA_SEGMENT_SIZE 30000
typedef void (*Callback)(void);
struct {
char cs[CODE_SEGMENT_SIZE]; /* Code Segment */
long ip; /* Instruction Pointer */
char ss[STACK_SEGMENT_SIZE]; /* Stack Segment */
long sp; /* Stack Pointer */
char ds[DATA_SEGMENT_SIZE]; /* Data Segment */
long bp; /* Base Pointer */
Callback fn[128];
} vm;
void vm_forward() {
vm.bp = (vm.bp + 1) % DATA_SEGMENT_SIZE;
}
void vm_backward() {
vm.bp = (vm.bp + DATA_SEGMENT_SIZE - 1) % DATA_SEGMENT_SIZE;
}
void vm_increment() {
vm.ds[vm.bp]++;
}
void vm_decrement() {
vm.ds[vm.bp]--;
}
void vm_input() {
vm.ds[vm.bp] = getchar();
}
void vm_output() {
putchar(vm.ds[vm.bp]);
}
void vm_while_entry() {
if (vm.ds[vm.bp]) {
vm.ss[vm.sp] = vm.ip - 1;
vm.sp++;
} else {
int c = 1;
for (vm.ip++; vm.cs[vm.ip] && c; vm.ip++) {
if (vm.cs[vm.ip] == '[') {
c++;
} else if (vm.cs[vm.ip] == ']') {
c--;
}
}
}
}
void vm_while_exit() {
if (vm.ds[vm.bp]) {
vm.sp--;
vm.ip = vm.ss[vm.sp];
}
}
void setup() {
int c;
int i;
memset(&vm, 0, sizeof(vm));
vm.fn['>'] = vm_forward;
vm.fn['<'] = vm_backward;
vm.fn['+'] = vm_increment;
vm.fn['-'] = vm_decrement;
vm.fn['.'] = vm_output;
vm.fn[','] = vm_input;
vm.fn['['] = vm_while_entry;
vm.fn[']'] = vm_while_exit;
for (i = 0; (c = getchar()) != EOF;) {
if (strchr(TOKENS, c)) {
vm.cs[i] = c;
i++;
}
}
}
void run() {
while (vm.cs[vm.ip]) {
vm.fn[vm.cs[vm.ip]]();
vm.ip++;
}
}
int main(int argc, char* argv[]) {
if (argc > 1) {
freopen(argv[1], "r", stdin);
}
setup();
run();
return 0;
}
--------------------------------
(以上内容来自 http://blog.youkuaiyun.com/redraiment/article/details/7483062,作者:redraiment)
代码清晰易懂,不再解释了。
上面提到的图灵完备之类的概念是计算机科学(CS)中的内容,有兴趣的可以自行参考维基百科介绍,然后再决定是否要进一步的了解。不过,先提个醒,CS 是个很大很引人入胜的领域,小心“沉迷”。