C语言的复杂程度绝对令人难以想象,同时由于一些特殊的原因,C里面同时存在
一些让人纠结的特性。
下面我们看一些有趣的C语言代码。
Exp:
main(){ printf(&unix["\021%six\012\0"], (unix)["have"] + "fun" - 0x60);}
第一步:
对于这样的代码要理解首先要做的是进行缩排,缩排后如下所示:
main() { printf( &unix["\021%six\012\0"], (unix)["have"] + "fun" - 0x60); }
如上面所示,还是不好理解,我们可以在缩排一下:
main() { printf( &unix["\021%six\012\0"], /
(unix)["have"] + "fun" - 0x60); }
第二步:
从上面缩排后的代码以及printf函数的函数原型:
size_t printf(const char *format,...);
我们知道在上面的代码中:
const char *format= &unix["\021%six\012\0"]
而我们的第一个可变参数为:
va_list[1]=(unix)["have"] + "fun" - 0x60); //这里简单的假设可变参数为一个数组型,具体可参与K&R的教程
接下来我们分析:
format指针; 在unix系统中, 有一个默认的定义,那就是:
#define unix 1
因此可以知道
*format= &unix["\021%six\012\0"]=&"\021%six\012\0"[1]
=&("\021%six\012\0"[1]) //这里表示指针的指向这个地方与&array[i]同样理解
这样可以知道:
*format="%six\012\0"="%six\021\0"
第三步:
分析(unix)["have"] + "fun" - 0x60可知:
(unix)["have"] + "fun" - 0x60= "have"[unix]+ "fun" - 0x60
="have"[1]+ "fun" - 0x60
='a'+ "fun" - 0x60
=97+ "fun" - 0x60
=97+ "fun" - 96
= "fun" +1
第四步:合并
将上面的*format和...可变参数合并,并用printf函数输出,则可以得到:
printf("%six\021\0","fun" +1);
这里以:
%s 输出 "fun"+1为地址的字符串, 因此输出: un
而
format 中的 ix\021\0 则输出 ix
因此合并起来输出的就是:
unix
我发现国内很多的教材对这里用到的很多知识点都没有透彻的说明,这其中当然包括我们大学
里面很多老师推荐的谭的教程,为了很好的理解C建议还是看看外国人写的书,毕竟C是老外发明的,
而且在翻译的过程中很多话很难找到完全一致的汉字来表示英语单词。
这就是: 英语比汉语更适合描述科技。 //不是我说的, 大家可以想想是不是这样。
不多说了,鉴于我的C语言水平实在有限,上面的分析难免有错误,欢迎各位大侠弯腰找板砖,