打印

6个变态的C语言Hello World程序ZT

[复制链接]
2929|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mohanwei|  楼主 | 2010-2-5 11:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚才搜索库函数说明的时候,发现这篇**,真是叹为观止:

6个变态的C语言Hello World程序
下面的六个程序片段主要完成这些事情:
  • 输出Hello, World
  • 混乱C语言的源代码
下面的所有程序都可以在GCC下编译通过,只有最后一个需要动用C++的编译器g++才能编程通过。
hello1.c
查看源代码
打印帮助

01    #define _________ }

02    #define ________ putchar

03    #define _______ main

04    #define _(a) ________(a);

05    #define ______ _______(){

06    #define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C)

07    #define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F)

08    #define ____ _(0x72)_(0x6C)_(0x64)_(0x21)

09    #define _____ __ ___ ____ _________

10    #include<stdio.h>

11    _____





hello2.c
查看源代码
打印帮助

1    #include<stdio.h>

2    main(){

3      int x=0,y[14],*z=&y;*(z++)=0x48;*(z++)=y[x++]+0x1D;

4      *(z++)=y[x++]+0x07;*(z++)=y[x++]+0x00;*(z++)=y[x++]+0x03;

5      *(z++)=y[x++]-0x43;*(z++)=y[x++]-0x0C;*(z++)=y[x++]+0x57;

6      *(z++)=y[x++]-0x08;*(z++)=y[x++]+0x03;*(z++)=y[x++]-0x06;

7      *(z++)=y[x++]-0x08;*(z++)=y[x++]-0x43;*(z++)=y[x]-0x21;

8      x=*(--z);while(y[x]!=NULL)putchar(y[x++]);

9    }



hello3.c
查看源代码
打印帮助

01    #include<stdio.h>

02    #define __(a) goto a;

03    #define ___(a) putchar(a);

04    #define _(a,b) ___(a) __(b);

05    main()

06    { _:__(t)a:_('r',g)b:_('$',p)

07      c:_('l',f)d:_(' ',s)e:_('a',s)

08      f:_('o',q)g:_('l',h)h:_('d',n)

09      i:_('e',w)j:_('e',x)k:_('\n',z)

10      l:_('H',l)m:_('X',i)n:_('!',k)

11      o:_('z',q)p:_('q',b)q:_(',',d)

12      r:_('i',l)s:_('w',v)t:_('H',j)

13      u:_('a',a)v:_('o',a)w:_(')',k)

14      x:_('l',c)y:_('\t',g)z:___(0x0)}

相关帖子

沙发
mohanwei|  楼主 | 2010-2-5 11:21 | 只看该作者
hello4.c
查看源代码
打印帮助
1            int n[]={0x48,
2            0x65,0x6C,0x6C,
3            0x6F,0x2C,0x20,
4            0x77,0x6F,0x72,
5            0x6C,0x64,0x21,
6            0x0A,0x00},*m=n;
7            main(n){putchar
8            (*m)!='\0'?main
9            (m++):exit(n++);}

hello5.c
查看源代码
打印帮助
01            main(){int i,n[]={(((1<<1)<<(1<<1)<<(1<<
02            1)<<(1<<(1>>1)))+((1<<1)<<(1<<1))), (((1
03            <<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<<(
04            1<<1)<<(1<<1))+((1<<1)<<(1<<(1>>1)))+ (1
05            <<(1>>1))),(((1<<1)<<(1<<1)<<(1<<1)<< (1
06            <<1))-((1<<1)<<(1<<1)<<(1<<(1>>1)))- ((1
07            <<1)<<(1<<(1>>1)))),(((1<<1)<<(1<<1)<<(1
08            <<1)<<(1<<1))-((1<<1)<<(1<<1)<<(1<<(1>>1
09            )))-((1<<1)<<(1<<(1>>1)))),(((1<<1)<< (1
10            <<1)<<(1<<1)<<(1<<1))-((1<<1)<<(1<<1)<<(
11            1<<(1>>1)))-(1<<(1>>1))),(((1<<1)<<(1<<1
12            )<<(1<<1))+((1<<1)<<(1<<1)<<(1<<(1>>1)))
13            -((1<<1)<<(1<<(1>>1)))),((1<<1)<< (1<<1)
14            <<(1<<1)),(((1<<1)<<(1<<1)<<(1<<1)<<(1<<
15            1))-((1<<1)<<(1<<1))-(1<<(1>>1))),(((1<<
16            1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<< (1
17            <<1)<<(1<<(1>>1)))-(1<<(1>>1))), (((1<<1
18            )<<(1<<1)<<(1<<1)<<(1<<1))- ((1<<1)<< (1
19            <<1)<<(1<<(1>>1)))+(1<<1)), (((1<<1)<< (
20            1<<1)<<(1<<1)<< (1<<1))-((1<<1)<< (1<<1)
21            <<(1<<(1>>1)))-((1<<1) <<(1<< (1>>1)))),
22            (((1<<1)<< (1<<1)<<(1<<1)<< (1<<1))- ((1
23            <<1)<<(1<<1)<<(1<<1))+((1<<1)<< (1<<(1>>
24            1)))), (((1<<1)<<(1<<1) <<(1<<1))+(1<<(1
25            >>1))),(((1<<1)<<(1<<1))+((1<<1)<< (1<<(
26            1>>1))) + (1<< (1>>1)))}; for(i=(1>>1);i
27            <(((1<<1) <<(1<<1))+((1 <<1)<< (1<<(1>>1
28            ))) + (1<<1)); i++) printf("%c",n[i]); }

hello6.cpp

下面的程序只能由C++的编译器编译(比如:g++)
查看源代码
打印帮助
01            #include <stdio.h>
02            #define _(_) putchar(_);
03            int main(void){int i = 0;_(
04            ++++++++++++++++++++++++++++
05            ++++++++++++++++++++++++++++
06            ++++++++++++++++++++++++++++
07            ++++++++++++++++++++++++++++
08            ++++++++++++++++++++++++++++
09            ++++i)_(++++++++++++++++++++
10            ++++++++++++++++++++++++++++
11            ++++++++++i)_(++++++++++++++
12            i)_(--++i)_(++++++i)_(------
13            ----------------------------
14            ----------------------------
15            ----------------------------
16            ----------------------------
17            ----------------i)_(--------
18            ----------------i)_(++++++++
19            ++++++++++++++++++++++++++++
20            ++++++++++++++++++++++++++++
21            ++++++++++++++++++++++++++++
22            ++++++++++++++++++++++++++++
23            ++++++++++++++++++++++++++++
24            ++++++++++++++++++++++++++i)
25            _(----------------i)_(++++++
26            i)_(------------i)_(--------
27            --------i)_(----------------
28            ----------------------------
29            ----------------------------
30            ----------------------------
31            ----------------------------
32            ------i)_(------------------
33            ----------------------------
34            i)return i;}

(全文完)

使用特权

评论回复
板凳
mohanwei|  楼主 | 2010-2-5 11:25 | 只看该作者
如果把int,float什么的也重新搞一下:
typedef int ____________;
typedef float ______________________;
……简直不让人活了

使用特权

评论回复
地板
mohanwei|  楼主 | 2010-2-5 11:35 | 只看该作者
Brainfuck
维基百科,自由的百科全书
跳转到: 导航, 搜索
Wikify **-2.svg
        此条目或章节需要被修正为维基格式以符合质量标准。(2008年8月28日)
请协助添加相关的内部链接来改善这篇条目。

Brainfuck,是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf***,甚至被简称为BF。
目录

    * 1 概述
    * 2 例子
          o 2.1 Hello World!
          o 2.2 当前位置清零
          o 2.3 字符I/O
          o 2.4 简单的循环
          o 2.5 指针维护
          o 2.6 加法
          o 2.7 条件指令
          o 2.8 加法
          o 2.9 乘法
    * 3 注
    * 4 外部链接

[编辑] 概述

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) {
]         }
[编辑] 例子
[编辑] Hello World!

一个在屏幕上打印"Hello World!"的程序:

++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.

[编辑] 当前位置清零

[-]

[编辑] 字符I/O

,.

从键盘读取一个字符并输出到屏幕上。
[编辑] 简单的循环

,[.,]

这是一个连续从键盘读取字符并回显到屏幕上的循环。注意,这里假定0表示输入结束,事实上有些系统并非如此。以-1和"未改变"作为判断依据的程序代码分别是",+[-.,+]"和",[->+>-<<]>[-<+>]>-<[-]<.[->>+<<],[->+>-<<]>[-<+>]>]"。
[编辑] 指针维护

>,[.>,]

通过移动指针保存所有的输入,供后面的程序使用。
[编辑] 加法

[->+<]

把当前位置的值加到后面的单元中(破坏性的加,它导致左边的单元被归零)。
[编辑] 条件指令

,----------[----------------------.,----------]

这个程序会把从键盘读来的小写字符转换成大写。按回车键退出程序。

首先,我们通过,读入第一个字符并把它减10(大多数情况下,brainfuck使用10作为换行符的值)。如果用户按的是回车键,循环命令([)就会直接跳转到程序的结尾:因为这时第一个字节已经被减到了零。如果输入的字符不是换行符(假设它是一个小写字符),程序进入循环。在这里我们再减去剩下的22,这样总共减掉32:这是ASCII码中小写字符和大写字符的差值。

下面我们把它输出到屏幕。然后接收下一个输入字符,并减去10。如果它是换行符,退出循环;否则,再回到循环的开始,减去22并输出……当循环退出时,因为后面已经没有其他的指令,程序也随之终止。
[编辑] 加法

,>++++++[<-------->-],,[<+>-],<.>.

这个程序对两个一位数做加法,并输出结果(如果结果也只有一位数的话):

4+3

7

(现在程序开始有点复杂了。我们要涉及到数组中单元的内容了,比如[0]、[1]、[2]之类。)

第一个输入的数字被放在在[0]中,从中减去48来把它从ASCII码值48到57转换为数值0到9:这是通过在[1]中放入6,然后按照[1]中的次数让一个循环从[0]中多次减去8来完成的(当加上或减去一个大的数值时,这是常用的办法)。下一步,加号被读入[1]中;然后,第二个数字被输入,覆盖掉加号。

下面的循环[<+>-]执行最重要的工作:通过把第二个数字移动到第一个里面让它们相加,并把[1]清空。这里的每次循环都把[0]增一并从[1]中减一;最终,在[1]被置零的多次循环中,[1]中的值就被转移到了[0]中。现在,[1]中是我们输入的换行符(这个程序里,我们没有设置对输入错误的检查机制)。

然后,指针被移回到指向[0],并输出它的内容([0]里面现在是 a + (b + 48) 的值,因为我们没有修改b的值,这等于 (a + b) + 48,也就是我们想要输出的ASCII值)。然后,把指针指向[1],里面保存着前面输入的换行符;输出换行符,程序结束。
[编辑] 乘法

,>,,>++++++++[<------<------>>-]
<<[>[>+>+<<-]>>[<<+>>-]<<<-]
>>>++++++[<++++++++>-],<.>.

和前一个程序类似,不过这次是乘法而不是加法。

第一个输入的数字被放入[0],星号和第二个数字被放入[1],然后两个数值都被校正:减去48。

现在,程序进入了主循环。我们的基本思想是:每次从[0]中减去一,同时把[1]的值加入到保存乘积的[2]中。在实际操作中,第一个内层循环把 [1]的值同时转移到[2]和[3]中,同时[1]清零(这是我们复制数字的基本方法)。下一个内层循环把[3]中的值重新放回到[1],并清零[3]。然后从[0]中减一,结束外层循环。在退出这个循环时,[0]中为零,[1]仍然是输入的第二个数值,[2]则是这两个数值的和。(要是想保存第一个数,我们可以在外层循环中每次给[4]加一,最后把[4]移回[0]。)

在结果中加48,并把换行符读入[3],输出ASCII码的乘积,然后输出刚才保存的换行符。
[编辑] 注

注意,这里数组的每个单元都是一个字节大小;-命令允许溢出,它可以用255个+命令来代替。同样,如果数组单元是有限、循环的,<可以用 29999个>命令代替。每个修改动作都可以被分解为最多7条指令。可是,两个连在一起的修改动作将会破坏“图灵完全”,因为这会把可能的内存状态限制到有限个数。(更确切的说,从这个角度看,现代的计算机依然不是完全意义上的“图灵完全”。)
[编辑] 外部链接

    * Brian Raiter, Muppetlabs. Brainfuck:八条指令的图灵完全编程语言。这个网站包括一个brainfuck程序quine。
    * Panu Kalliokoski. Brainfuck档案有许多brainfuck实现、程序和quine.
    * Cat's Eye Technologies. Brainfuck
    * Frans Faase. BF is Turing Complete
    * Brainfucked - Brainfuck Compiler

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

177

主题

9320

帖子

24

粉丝