首页 > 代码库 > Brainfuck 编程语言
Brainfuck 编程语言
很偶然的机会认识到这个语言,当时在纸上对着它的 "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.csdn.net/redraiment/article/details/7483062,作者:redraiment)
代码清晰易懂,不再解释了。
上面提到的图灵完备之类的概念是计算机科学(CS)中的内容,有兴趣的可以自行参考维基百科介绍,然后再决定是否要进一步的了解。不过,先提个醒,CS 是个很大很引人入胜的领域,小心“沉迷”。
Brainfuck 编程语言