幾道C/C++考題

來源:互聯網
上載者:User

題目來自水木BBS

1. 以下兩個定義及初始化有什麼區別和聯絡:
char pch[] = "Hello world";
char *str = "Hello world";
2. static關鍵字用在哪幾種場合,各起什麼作用
3. 在典型的系統,比如win32,在調用C的main之前發生了什麼事情,另外有時候main函數是有int的傳回值,它的傳回值做什麼用途?
4. C語言程式編譯完之後,運行起來,其儲存映像包括哪幾部分,各起什麼作用?
5. C語言傳參數的機制是什麼,也就是通過什麼機制傳遞參數的?

 

解答:

1. 第一個是字元數組,字元內容可以被修改;第二個指向"Hello world"常量的指標,字元內容不能被修改。

詳細的解釋:http://blog.chinaunix.net/u3/110791/showart_2248052.html

 

2. 略

 

3.  main函數之前--真正的函數執行入口或開始

一種解釋

實際上,在可執行檔被載入之後,控制權立即交給由編譯器插入的Start函數,它將對後面這些全域變數進行準備:
   _osver 作業系統的構件編號
      _winmajor 作業系統的主要版本號
      _winminor 作業系統的次版本號碼
      _winver 作業系統完全版本號碼
      __argc 命令列參數個數
     __argv 指向參數字串的指標數組
      _environ 指向環境變數字串的指標數組
Start函數初始化堆並調用main函數.mian函數返回之後,Start函數調用Exit函數結束該進程.
啟動函數Start的原始碼在:
   crt0.c Microsoft Visual C++
      c0w.asm Borladn C++

另一種解釋

Some of the stuff that has to happen before main():
set up initial stack pointer
initialize static and global data
zero out uninitialized data
run global constructors

Some of this comes with the runtime library's crt0.o file or its __start() function. Some of it you need to do yourself.
Crt0 is a synonym for the C runtime library.
Depending on the system you're using the follwing may be incomplete, but it should give you an idea. Using newlib-1.9.0/libgloss/m68k/crt0.S as an outline, the steps are:
1. Set stack pointer to value of __STACK if set
2. Set the initial value of the frame pointer
3. Clear .bss (where all the values that start at zero go)
4. Call indirect of hardware_init_hook if set to initialize hardware
5. Call indirect of software_init_hook if set to initialize software
6. Add __do_global_dtors and __FINI_SECTION__ to the atexit function so destructors and other cleanup functions are called when the program exits by either returning from main, or calling exit
7. setup the paramters for argc, argv, argp and call main
8. call exit if main returns

第三種解釋:囫圇C語言(三):誰調用了我的 main?
    
    現在最重要的是要跟得上潮流,所以套用比較時髦的話,誰動了我的乳酪。誰調用了我的 main?不過作為電腦工作者,我勸大家還是不要趕時髦,今天Java熱,明天 .net 流行,什麼時髦就學什麼。我的意思是先花幾年把基本功學好,等你趕時髦的時候也好事半功倍。廢話不多說了。  
    我們都聽說過一句話:“main是C語言的入口”。我至今不明白為什麼這麼說。就好像如果有人說:“掙錢是泡妞”,肯定無數磚頭拍過來。這句話應該是“掙錢是泡妞的一個條件,只不過這個條件特別重要”。那麼上面那句話應該是 “main是C語言中一個符號,只不過這個符號比較特別。” 
    1. 編譯器預設是找 __start 符號,而不是 main
    2. __start 這個符號是程式的起始點
    3. main 是被標準庫調用的一個符號
    
    再來思考一個問題:
    我們寫程式,比如一個模組,通常要有 initialize 和 de-initialize,但是我們寫 C 程式的時候為什麼有些模組沒有這兩個過程麼呢?比如我們程式從 main 開始就可以 malloc,free,但是我們在 main 裡面卻沒有初始化堆。再比如在 main 裡面可以直接 printf,可是我們並沒有開啟標準輸出檔案啊。   
    聰明的人民群眾會想,一定是在 main 之前幹了些什麼。使這些函數可以直接調用而不用初始化。通常,我們會在編譯器的環境中找到一個名字類似於 crt0.o 的檔案,這個檔案中包含了我們剛才所說的 __start 符號。(crt 大概是 C Runtime 的縮寫)
    
    那麼真正的 crt0.s 是什麼樣子呢?下面我們給出部分虛擬碼:    
    ///////////////////////////////////////////////////////
    section .text:
    __start:
    
     :
     init stack;
     init heap;
     open stdin;
     open stdout;
     open stderr;
     :
     push argv;
     push argc;
     call _main; (調用 main)
     :
     destory heap;
     close stdin;
     close stdout;
     close stderr;
     :
     call __exit;
    ////////////////////////////////////////////////////
    
    實際上可能還有很多初始化工作,因為都是和作業系統相關的,筆者就不一一列出了。
    
    注意:
    1. 不同的編譯器,不一定預設得符號都是 __start。
    2. 彙編裡面的 _main 就是 C 語言裡面的 main,是因為彙編器和C編譯器對符號的命名有差異(通常是差一個底線'_')。

    
總結:
main函數執行之前,主要就是初始化系統相關資源:
1.設定棧指標
2.初始化static靜態和global全域變數,即data段的內容
3.將未初始化部分的賦初值:數值型short,int,long等為0,bool為FALSE,指標為NULL,等等,即.bss段的內容

4.運行全域構造器,估計是C++中建構函式之類的吧
5.將main函數的參數,argc,argv等傳遞給main函數,然後才真正運行main函數

main函數執行之後,釋放資源,結束進程。

 

備忘:全域的未初始設定變數存在於.bss段中,具體體現為一個預留位置;全域的已初始設定變數存於.data段中;而函數內的自動變數都在棧上分配空間。.bss是不佔用.exe檔案空間的,其內容由作業系統初始化(清零);而.data卻需要佔用,其內容由程式初始化。

 

4. 程式碼片段、唯讀資料區段、讀寫資料區段、未初始化資料區段屬於靜態地區,而堆和棧屬於動態地區。程式碼片段、唯讀資料區段和讀寫資料區段將在串連之後產生,未初始化資料區段將在程式初始化的時候開闢,而堆和棧將在程式的運行中分配和釋放。在靜態映像檔案中,各個部分稱之為節(Section),而在運行時的各個部分稱之為段(Segment)。如果不詳細區分,可以統稱為段。

詳細的解釋:http://book.51cto.com/art/200902/111807.htm

 

5. 通過堆棧操作實現參數的傳遞。

  1. 進程的堆棧儲存區是主調函數和被調函數進行通訊的主要區域。
  2. C語言中參數是從右向左進棧的。
  3. 由主調函數在調用後清理堆棧。(備忘2)
  4. 函數的傳回值一般是放在寄存器中的。

 

參看文章:

http://witmax.cn/c-function-heap-stack.html

http://read.newbooks.com.cn/info/178095.html

http://nforcex.blogbus.com/logs/7537173.html

備忘:

  1. C語言中傳遞參數為值傳遞(包括指標傳遞);C++添加了引用傳遞。要注意指標傳遞和引用傳遞的區別。

  2. C語言使用的是cdcel調用,但是windows驅動程式中使用的是stdcall調用。cdcel是主調函數在調用後恢複堆棧,stdcall是被調用函數返回時自行恢複堆棧。

  3. Linux彙編使用的是AT&T文法與Intel或MASM彙編文法不同。比如:指令操作的源地址和目的地址的位置剛好是反的。 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.