6个变态的C语言Hello World程序——更好的理解C
下面这个程序片段主要完成以下两件事情:
1)完成输出Hello World。
2)混乱C语言代码。
#define _________ } #define ________ putchar #define _______ main #define _(a) ________(a); #define ______ _______(){ #define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C) #define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F) #define ____ _(0x72)_(0x6C)_(0x64)_(0x21) #define _____ __ ___ ____ _________ #include<stdio.h> _____这里面主要涉及到的就是#define宏定义的使用技巧及ASCII码字符集。
首先,让我们来熟悉回顾下#define的具体用法:
宏定义的格式:#define 宏名 宏定义字符串
注意:宏定义只在编译预处理中起作用,不是真正的C语句行尾无需分号;宏名与宏定义字符串之间采用空格分隔,所以宏定义字符串中间不能有空格。宏替换对引号内的宏名无效。
以下是用法:
"定义符号常量" #define PI 3.1415926 "给程序书写带来方便" #define LONG_STRING "it is really a long longlong long string" printf(LONG_STRING); "嵌套的宏定义" #define PI 3.14 #define S PI*r*r "宏定义作用范围" 宏定义可以写在程序中任何位置,作用范围从定义处到文件爱结尾。 可通过#undef强制指定结束范围 "带参数的宏定义" #define SQR(x) x*x #define SQR(x) (x)*(x) //执行过程,在程序编译时现用实参替换形参,然后用宏定义字符串完成整个替换。 //若SQR(X)是一般声明的函数,对他的处理要等到程序执行时才进行。 //注意两者的区别,宏定义只是简单的字符替换。当x=a+b时,两者分别表示 //a+b*a+b和(a+b)*(a+b) "宏定义指针类型时的坑" #define Pointer int * Pointer a,b; //始终牢记#define只是简单的字符替换,这里的b是int型 。正确方法如下: typedef int * Pointer;//不要漏掉分号 Pointer a,b; "编译预处理" #define FLAG #if FLAG statement 1 #else statement 2 #endif //statement 1与statement 2只有一段会被编译到源程序里面 "防止头文件的重复包含" #ifndef FUNCTION_H_INCLUDED #define FUNCTION_H_INCLUDED #endif // FUNCTION_H_INCLUDED
字符与ASCII码的对应关系:
0x48='H' 0x65='e' 0x6c='l' 0x6f='o' 0x2c=',' 0x20=' ' 0x77=''w 0x72='r' 0x64='d' 0x21='!'
到这里,我们再回头看看如何理解一开始的那个BT的Hello World程序。
如图所示,我已经不同类型的下划线分别做了不同的记号表示,然后我们可以开始简单的字符替换了:
由行号11可得到行号9的宏定义字符串;蓝色可替换成行号6的宏定义字符串,红色可替换为行号7的宏定义字符串,黄色可定义成行号8的宏定义字符串,下划线1替换为}
______ _(0x48)_(0x65)_(0x6C)_(0x6C) _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F) _(0x72)_(0x6C)_(0x64)_(0x21)}
按照如上所示方法,全部替换后程序转换为
main(){putchar('H');putchar('e');putchar('l');putchar('l');putchar('o');putchar(',');putchar(' ');putchar('w');putchar('o');putchar('r');putchar('l');putchar('d');putchar('!');}
看似非常混乱的C代码翻译之后还是很直观的,虽然只是很简单的替换,但我觉得这样的混乱真的让C变得挺有意思的!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。