今天看一篇博主的文章,提到了添加一行代码输出hello world的有趣题目,于是在网上搜,发现关于hello world的小伎俩还真不少,当然,问题的关键不在hello world上,而在这背后的原理之中。那么我们就来看一看这些小题目吧!
题目一:如下,在print()函数中填充代码,使之显示hello ,world,要求main() 不作改动
/* c/c++ code */
#include "stdio.h"
void print(){}void main(){}
显然,这有两种思路来结局,因为main函数中没有任何执行代码,所以解决方案一种是在main()函数本身打主意,一种是看看能不能在main()函数执行之前就解决问题。
请看第一种解决方案(思路一):
#include <stdio.h>#include <stdio.h>void print(){#define main main(){ printf("hello,world");}\
void ccav}void main (){}
这个解法非常巧妙,但是运用的思维却非常简单,宏定义可以定义在任何地方,在编译阶段宏定义就已经完全展开,也就说,编译完成之后,程序实际上就变成了这幅摸样:
#include <stdio.h>void print(){}void main (){printf("hello,world");
}void ccav(){}
解法二(思路二)思路是这样的,抢在main函数执行之前先做点什么,代码如下:
这个思路很巧妙,破除了思维定势,人们的第一印象一般是如果main函数都进不去,怎么执行,但是却忘了程序入口点是可以改的,但是需要说明的是这个依赖于具体的编译器,像我用的gcc就不行,但是在vs2008中是可以的,另外,需要说明的是(与本题无关,纯属闲话),main 函数返回值如果是void ,在g++中编译都过不了,具体分析请看 这篇博客 。#include "stdio.h"
void print(){#pragma comment(linker, "/entry:print1")
printf("hello world\n");
}int main(){}
解法三如下,虽然我不推荐,而且也是依赖于具体的编译器,调试环境,而且这个解法有点取巧的嫌疑,但是也可以作为一个思想
这个思路的原理是全局变量的初始化是在main函数执行之前。#include "stdio.h"
void print(){}int tmp = printf("hello world\n");//}
void main(){}
int main(){
if(/*在此填入一个语句*/) printf("Hello");else printf(" World!");}
输出 Hello World!
解法:
说明: fork有一个特点,就是同一个函数有至少两个返回值,在父进程中返回非零的数,在子进程中返回0,因此呢,在上面的代码中,如果进入的是子进程,那么!fork()为1,wait()不用执行,输出hello,而如果是父进程,!fork()为0,需要接着检查,要等一会,确保了先输出hello,在输出world,需要支持的是,fork()和wait()是linux系统调用,这个程序在windows os上是跑不通的,即便是在minGW这种windows下的gcc编译器中也不行。#include "unistd.h"
#include "stdio.h"
int main(){
if ( !fork() || (!wait()) ) //子进程打印hello,父进程等待子进程结束printf("hello");
else
printf("world!");//子进程结束后,父进程打印world!}