chapter 0:
之前有人开玩笑说码农工资按代码行数来算的,现在有个办法让你瞬间变成富富富!
先写几行代码:“a.c”
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int main(){
return 0;
}
gcc a.c -save-temps
运行上面的命令(微软VS工具也可以),看看多了几个文件,其中有个特别的“a.i”文件。编译这个文件和编译“a.c”是完全等价的。用文本编辑器打开a.i看看,一万六千多行。提交代码的时候,把a.i重命名为a.c交上去,笑。
chapter 1: 混乱C
国际C语言混乱大赛每届的比赛都有许多精品代码,让人看了之后抓狂。
1、前处理器命令(Preprocessing Symbol Definition)
代码文件:a.c
A
gcc a.c -save-temps -DA=main(){printf(\"HelloWorld!\");}
这利用的宏定义,我们将A定义为一个宏,当GCC处理源码时,会将A替换为对应的宏。
2、Makefile和C混合
这个可能看起来有些奇怪,这一个代码文件既是源码又是Makefile,所以可以用
mingw32-make -f tomx.c
来自:IOCCC 2000 tomx
#include <stdio.h>
#define true
true /*:all
CC=cc
PROG=tomx
false :
make -f $0 $1
exit 0
all: $(PROG)
%:%.c
$(CC) $< -o $@
clean:
rm $(PROG)
.PHONY: /* true clean */
int main() {return!printf("Hello, world\n");}
其中C的注释以“/*”开头的话只会在第一次遇到“*/”时结束。这样makefile的脚本就隐藏到了注释里面,而make程序解释的时候这个代码刚好符合makefile的语法。
3、滥用C的转移符号和内置符号等
来自:IOCCC 1998 schweikh2
#define _POSIX_SOURCE /* you are not supposed to understand this */
#define O(OOO,OO0,O00,O0O,OO,O0)\0##O0O%:%:OO\0##O0%:%:OOO\0##OO0%:%:O00
#include<signal.h>
static volatile sig_atomic_t One;
#include<stdlib.h>
#include<unistd.h>
#define Zero(NULL)#NULL
#define ONE(One) Zero(One)
in??/
t
#line 10 "01\015"
main (register zero, char **ONE)
%:
<% switch (sizeof __FILE__ < zero) case 1: return One /= zero;
{ auto one = zero = atoi (ONE<:zero-1:>);
do for (one += alarm (One |= (signal (__LINE__, (void(*)(register))main)
!= SIG_ERR)); One; ++one);
while (zero -= write (1, __FILE__+(one&1), 1));
return write (1, 1+__FILE__+1, 1) != 1;
%>}
// Will the next line be executed????????????????/
a++;
/??/
* A comment *??/
/
// Will the next line be executed??????????????a++;
/* A comment */
4、语法
来自:IOCCC 1990 baruch
v,i,j,k,l,s,a[99];
main()
{
for(scanf("%d",&s);*a-s;v=a[j*=v]-a[i],k=i<s,j+=(v=j<s&&(!k&&!!printf(2+"\n\n%c"-(!l<<!j)," #Q"[l^v?(l^j)&1:2])&&++l||a[i]<s&&v&&v-i+j&&v+i-j))&&!(l%=s),v||(i==j?a[i+=k]=0:++a[i])>=s*k&&++a[--i])
;
}
5、C的特殊语法
来自:IOCCC 1986 stein
typedef char*z;O;o;_=33303285;main(b,Z)z Z;{b=(b>=0||(main(b+1,Z+1),*Z=O%(o=(_%
25))+'0',O/=o,_/=25))&&(b<1||(O=time(&b)%0250600,main(~5,*(z*)Z),write(1,*(z*)Z
,9)));}
typedef char*z;
O;
o;
_=33303285;
main(b,Z)
z Z;
{
b=
(b>=0
||
(main(b+1,Z+1),
*Z=O%(o=(_%25))+'0',
O/=o,
_/=25))
&&
(b<1
||
(O=time(&b)%0250600,
main(~5,*(z*)Z),
write(1,*(z*)Z,9)));
}
int main(argc, argv)
int argc,
char **argv;
{
return 0;
}
6、看不清的符号
来自:IOCCC 1985 lycklama
#define o define
#o ___o write
#o ooo (unsigned)
#o o_o_ 1
#o _o_ char
#o _oo goto
#o _oo_ read
#o o_o for
#o o_ main
#o o__ if
#o oo_ 0
#o _o(_,__,___)(void)___o(_,__,ooo(___))
#o __o (o_o_<<((o_o_<<(o_o_<<o_o_))+(o_o_<<o_o_)))+(o_o_<<(o_o_<<(o_o_<<o_o_)))
o_(){_o_ _=oo_,__,___,____[__o];_oo ______;_____:___=__o-o_o_; _______:
_o(o_o_,____,__=(_-o_o_<___?_-o_o_:___));o_o(;__;_o(o_o_,"\b",o_o_),__--);
_o(o_o_," ",o_o_);o__(--___)_oo _______;_o(o_o_,"\n",o_o_);______:o__(_=_oo_(
oo_,____,__o))_oo _____;}
7、直接写二进制代码
来自:IOCCC 1984 mullender
short main[] = {
277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800,
-113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004,
14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9,
4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419,
0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0,
4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#',
0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712,
'p', 072163, 'r', 29303, 29801, 'e'
};
8、语法
来自:IOCCC 1987 korn
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
9、语法
来自:原创
#include<stdio.h>
int lastYear (int l)
{if(!l)printf("Year!\n"); return l;}
int (*thisYear(char *t)) (int l)
{printf("%s", t); return lastYear;}
int (*(*nextYear(double n))(char *t)) (int l)
{printf("Happy ");return thisYear;}
int main(argc, argv)int argc; char **argv;{return (nextYear(0.001)("New ")(0));}