linux下CPP的认识

来源:互联网 发布:最好看的网络历史小说 编辑:程序博客网 时间:2024/05/16 16:58

linux中命令cppC Preprocessor的缩写,而不是C++那个后缀名称。

先来个关于printf奇怪用法的程序,这个程序是一个牛人写的,得过大奖,背景在此就不多说了,有闲情想了解的同志们去百度吧。在linuxunix平台上运行的结果是unix

 

 

这个程序在CU上有帖子讨论:

http://bbs.chinaunix.net/thread-580042-1-1.html

Linux forum上也有讨论:

http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=program&Number=386653&page=2&view=collapsed&sb=5&o=all&fpart=

下面是后者中的一些解答部分,本人才疏学浅,不敢在此发表自己见解。

 

因为:数组str[n] <==>(n)[str]

所以:(unix)["have"] + "fun" - 0x60 <==> "have"[1]+"fun"-0x60

即: 'a'+"fun"-0x60

因为:'a' = 0x61

所以:变为“fun”+1(隐含了同类型运算优先?)

因为:“fun”是个char型指针

所以:指向“un”

因为:/021是一个八进制数,代表第一个字符

所以:&1["/021unix/012/0"]<==>"unix/012/0"

因为:012是八进制的换行,/0是字符串结束

所以:最终结果是

unix

[提示符]$

 

printf(&unix["/021%six/012/0"], (unix)["have"] + "fun" - 0x60);
==> printf(&1["/021%six/n/0"], (1)["have"] + "fun" - 0x60);
==> printf(&"/021%six/n/0"[1], "have"[1] + "fun" - 0x60);
==> printf("%six/n", 'a' + "fun" - 0x60);
==> printf("%six/n", 0x61 + "fun" - 0x60);
==> printf("%six/n", "fun" + 1);
==> printf("%six/n", "un");

 

理解这个程序需要知道数组的那个诡异但正确的用法,取地址,指针运算,UNIX/Linux编译器的熟悉程度(说白了就是要知道unix是一个已经预定义好的宏,见下文),当然还要知道十六进制和八进制表示方法。

$cpp -dM /dev/null > macro-on-linux.txt

(其中的/dev/null可用C文件代替,添加选项-std=c99可得不同结果,详细用法请man cpp,实际结果请实践之)

macro-on-linux.txt文件中内容如下,这里删除了其中很多内容,其中unix藏在某个角落里,所以,上面的程序如果使用下面许多宏来代替,结果是一样的。

 

#define __DBL_MIN_EXP__ (-1021)

#define __FLT_MIN__ 1.17549435e-38F

#define __unix__ 1

#define __DBL_MIN_10_EXP__ (-307)

#define __FINITE_MATH_ONLY__ 0

#define __GNUC_PATCHLEVEL__ 0

#define __linux 1

#define __DEC32_EPSILON__ 1E-6DF

#define __unix 1

#define __LDBL_MAX_EXP__ 16384

#define __linux__ 1

#define __SIZEOF_LONG__ 4

#define __DECIMAL_DIG__ 21

#define __gnu_linux__ 1

#define __LDBL_HAS_QUIET_NAN__ 1

#define __GNUC__ 4

#define __DEC32_MIN__ 1E-95DF

#define __DBL_MAX_EXP__ 1024

#define __SIZEOF_SIZE_T__ 4

#define __NO_INLINE__ 1

#define __i386 1

#define __FLT_MANT_DIG__ 24

#define __VERSION__ "4.3.0 20080428 (Red Hat 4.3.0-8)"

#define unix 1

#define __i386__ 1

#define __SIZE_TYPE__ unsigned int

#define __ELF__ 1

#define linux 1

#define __FLT_MIN_10_EXP__ (-37)

#define __INTMAX_TYPE__ long long int

#define i386 1

#define __STDC__ 1

#define __PTRDIFF_TYPE__ int

#define __GNUC_GNU_INLINE__ 1

这些宏都是预定义好了的,就像__cpluscplus__func__那些一样。网上说是编译器内建的,在具体文件是找不到的,我功底不深,不能从原理上解释,见谅。

个人觉得,如果想在linux下搞些开发,这些知识应该要懂一点,多知道一些总不是坏事。

原创粉丝点击