幾個玩具代碼(不用main的編程)

打印編譯時間

#include <stdio.h>
int main()
{
    printf("本程序的編譯時間爲:%s  %s\n",__DATE__,__TIME__);
    //  printf("%d\n",__LINE__);
    return 0;
}

這裏寫圖片描述
主函數main爲空的情況下輸出helloworld

/*********/
void main()
{
}
/*********/

//以上的main函數不能修改,/***/可隨意添加代碼,至少4中方法

第一種:

#include <iostream>
using namespace std;

class A
{
public:
   A()
   {
      cout<<"Hello World"<<endl;
   }
};
A a;
void main()
{

}

第二種:

#include <iostream>
using namespace std;

#define main() main(){cout<<"Hello World"<<endl;} void test()

void main()
{

}

第三種:

#include <iostream>
using namespace std;

int print();
int a=print();
int print()
{
   cout<<"Hello World"<<endl;

   return 0;
}
void main()
{

}

第四種:利用VC6修改主函數的入口

#include <stdio.h>
#pragma comment(linker,"/entry:fun")
#pragma comment(lib,"msvcrt.lib")
int fun()
{
    printf("hello world\n");
    return 0;
}

void main()
{
    ;
}

這裏寫圖片描述

暫時只有這四種了。。。。。註明一下,第四種還可以這樣玩. = =

#include <stdio.h>
#pragma comment(linker,"/entry:fun")
#pragma comment(lib,"msvcrt.lib")
void main();
int fun()
{
    printf("hello world\n");
    main();
    printf("hello world\n");
    return 0;
}

void main()
{
    printf("main start\n");
}

這裏寫圖片描述
這樣就實現用其他函數去調動去main函數了……只是玩一下而已的東西,,,說了這麼多,實際上是想表達main不是真正的程序的入口。在main之前有一些函數已經執行了,它們幫你分配堆棧,初始化寄存器。在main之後也有一些函數執行了,他們幫你做收尾工作。。。
好吧,抽象的話都是沒人鳥的。上一個Demo吧 - -!

#include <stdio.h>
void main()//VC下會崩潰!!VS不會
{
    int x = 0;
    scanf("%f",&x);
}

這個代碼應該能看懂吧,但是你故意用浮點數格式去進行輸入。那麼命運只有一個就是崩潰,上圖….
這裏寫圖片描述
但是如果你這樣

#include <stdio.h>
void main()
{
    float a = 1.0;
    int x = 0;
    scanf("%f",&x);
}

這裏寫圖片描述
看到了吧,能夠成功執行,並且沒有崩潰。
那麼爲什麼呢???
加入了一個看似沒什麼影響的float a = 1.0;對編譯器產生了什麼樣的影響?
= =!一般來說吧,當編譯器見到了有float a = 1.0;這樣子明顯用過浮點數的痕跡,就會主動在main函數之前初始化浮點寄存器。這是第一點。然後還有一點,這是一條規則,凡是使用沒有初始化的浮點寄存器,那麼進程就只有崩潰的命運。
就是這兩條,構成了程序崩潰的條件,呃,要說明一點,在VS下,已經成功修復了這個BUG。現在已經不管什麼用了沒有浮點數的痕跡,一上來就初始化浮點數寄存器了。。
說了這麼多,只說了一點,main之前有函數執行,main函數之後也有函數執行。。。。

再給一個玩具代碼,可以跳過n個函數

#include <iostream>
using namespace std;
void Show()
{
    cout<<"hello world"<<endl;
}
void fun()
{
    void *p = NULL;
    p = &p+2;
    *(int*)p += 5;
}
void main()
{
    Show();
    fun();//執行一個fun函數讓跳過後面的Show函數
    Show();
    Show();
    Show();
}

這裏寫圖片描述
這個用到了越界訪問函數返回地址的原理。給出函數棧幀上的內存分佈
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章