|
今天翻前两天刚送到的《C专家编程》,章节8.10的那个IOCCC 1987年的获奖作品让我觉得很好玩。 - 9 n! B& W1 E8 k* ?( O; w- i u: o
- main(){ printf(&unix["/021%six/012/0"], (unix)["have"] + "fun" - 0x60);}
复制代码 ' Y5 J+ w, M6 A4 m# h% |$ k, ]
作者这里利用的第一个技巧并不算太晦涩:"a = i[a]= *(a+i)“ 即下标运算符的可交换性。 . m$ r5 m1 c% r$ C5 G3 G
但是这个老天爷的unix和&unix是怎么回事? $ {% L3 a& Z: _/ x' ]
我把自己脑子里有印象的C的最隐蔽的角落回想了一遍,难道是trigraph之类的特殊符号?查了查不是 ( w2 \3 h1 a' w; C2 q& ~7 U
正推不行,就反推吧。编译运行后,输出结果是“unix“。如此说来“(unix)["have"] + "fun" - 0x60)“这个表达式的结果应该是指向"un"的char * ;因此,“(unix)["have"] - 0x60"的值应该是整数1才对;因此“(unix)["have"]"的值应该是0x61;这就豁然开朗了,0x61='a',是"have"中的第二个字符,所以unix的值必然为1。
& X- |% s) N: S" A( u
这个反推是否正确呢? 利用gcc看一下只进行preprocessor处理后的代码:
- l! j0 a2 |3 b- whodare@whodare:~/programming/c++$ gcc -E 1.c
' z. K" e3 \+ [ - main()
7 v) o& @: O1 Z* @& x8 v - {
. u* E. j1 L; B: d4 X" z - printf(&1["/021%six/012/0"], (1)["have"] + "fun" - 0x60) ;& l- ^* H2 i% B0 w0 q
- }
复制代码
1 A; P3 I" H4 v2 U/ n% w5 W8 N2 v0 w6 L2 `/ B% I @' r
正确。unix看来是属于预定义的marco,值为1。拿“gcc predefined marco"为关键字google了一下,找到可信资料了: http://gcc.gnu.org/onlinedocs/cpp/System_002dspecific-Predefined-Macros.html#System_002dspecific-Predefined-Macros 6 x4 H) L5 Z8 ]1 e B
原来unix这个宏是属于gcc提供的 System-specific Predefined Macros,因此这个奇妙的函数只能在*nix环境下正常工作。
% ~( j9 I" D! ?; g
可以查看更多的gcc提供的predefined marco - & x2 }& g1 X- q9 q
- gcc -dM -E 1.c
复制代码 2 p6 f+ Q2 f. I- ^
顺便附上历史文献,哈哈 - & a& z/ }; o# D O! r0 R# Z
- Best One Liner:/ D' s1 O7 L/ I$ k* `( u
- : G# u3 W4 r! z2 s" y
7 {7 J2 H4 F2 x- David Korn
9 ~. f+ {$ s( o; B0 A2 a; R - AT&T Bell Labs
8 | r9 V- i& V6 `* K' N: a+ V4 f - MH 3C-526B, AT&T Bell Labs9 @ n3 y& P: o4 I5 y
- Murray Hill, NJ/ _: ~' O; w& L" n# [
- 07974% _. _: S; O' \$ Y r7 l
- USA
* D$ R8 L: U* s# U) \
) n: w, y5 D* I9 ]0 Z- The Judges believe that this is the best one line entry ever received.* P+ P1 N/ V1 d! Y. g
- Compile on a UN*X system, or at least using a C implementation that2 z) b5 U, S; a/ t4 U$ A8 z/ W
- fakes it. Very few people are able to determine what this program, H9 z$ \2 X5 ?; X8 W
- does by visual inspection. I suggest that you stop reading this
# l2 d1 t+ D1 N1 t- Q! o2 e - section right now and see if you are one of the few people who can.0 B1 O( O$ }+ R8 C
- " ^3 j. w! M. L2 e
; t3 e- N" [/ P/ F1 {1 G% B- m- Several points are important to understand in this program:
2 O$ K5 U8 g, j2 p7 k2 A - " {6 v6 Y) |; R" s& T' V; r
- / ^/ D1 h( A2 S7 W/ [
- 1) What is the symbol `unix' and what is its value in the program?8 I& c" O0 v! q; g0 S
- Clearly `unix' is not a function, and since `unix' is not declared
- v. J) t% s) \. a: E - to be a data type (such as int, char, struct foo, enum, ...); B1 e$ [: ^8 h
- what must `unix' be?
# W- t$ I2 q; N* w3 X- C' n
& { n+ N# t, a# e1 F7 e$ i9 f
6 y" P5 s( e$ h' K1 g. G- 2) What is the value of the symbol "have"? (hint: the value is- n# j% i1 j# Z- Y
- NOT 4 characters, or 'h', or a string) Consider the fact that:( D9 O3 L. v& Z5 z! A
9 |# _, }, e3 S8 g% u/ [
# _& [' _. B, r' V$ d! P- char *x;0 `( U2 M8 k; a7 P5 G1 |0 W
- - s( I7 m! H# M9 s5 Q; U2 S/ Q
- ( K+ w5 y6 }6 w( v( G1 a
- defines a pointer to a character (i.e. an address), and that
: G N0 ^* I+ q% \" C3 x - the `=' assigns things is compatible types. Since:" C+ S! w' r$ _( c M& j
- " R. J- \1 a) i' a
- ; w9 Y. t: y5 f
- x = "have";
8 U+ o* P. f" N, o. n+ X) }
7 O4 d- J. c6 u/ V2 n
- o% \+ b( x* w. a) _/ w" y- is legal C, what type of value is "have"?
+ ~; I- j" V( g4 ?8 W/ q" z
) k& i2 u& i9 f
! A; [: s% Q8 Z7 ^- 3) Note that the following expressions yield the same value:% L7 D+ b5 {; R
- (unix)["have"] + "fun" - 0x60)! X$ Z( i! v9 f2 w
- x[3] *(x+3) *(3+x)
9 h! y+ L" f9 n. |. S$ s) C: s; I - 8 c" e2 o4 U; n7 m& l
- , p) t3 l4 F" x% x" ]
- since addition is communitive. What can be said about the value:( e: m4 C* ?1 @1 v
4 s; C9 J1 k" g+ U! ^+ n. P; T
% W- S/ M) M# Q* n2 r- 3[x]
复制代码
9 c0 Z- ]/ ^4 L2 Q
# a* g- }7 P$ @9 z |