作者ggg12345 (ggg)
看板Soft_Job
標題Re: [心得] 程式設計師應該懂多少?
時間Fri Jun 5 10:29:08 2009
※ 引述《xsion (Xsion)》之銘言:
: 標題: [心得] 程式設計師應該懂多少?
: Q: 下面這段程式有沒有什麼問題?
: void fun(int* ptr)
: {
: ptr = new int[2];
: }
: int main()
: {
: int *ptr = NULL;
: fun(ptr);
: ptr[1] = 1;
: ptr[2] = 2;
: printf("%d %d", ptr[1], ptr[2]);
: return 0;
: }
:
: 我期待中的出淺的Programmer起碼會看出「有使用new配置記憶體,卻沒delete釋放」
: 「C語言是base-0陣列宣告大小為2的不能索引到[2]」,我想有點程度的應該還能回答
: C語言都是傳值呼叫,所以配置好的指標空間無法回傳。
: 我還想看得出錯誤的人還可以討論怎麼修改會比較好...
:
: 好吧,或許你們都用C++ Builder或.Net,有好用的data structure class可以用,
: 所以我改問...
: Q:當有不定資料長度的資料要儲存時,你會使用什麼方法。
: A:不定長度?
: Q 補充道:就是一開始不知道需要多大空間,要動態配置的啊。
: A:不是寫程式時就知道大小了嗎?
: Q又補充道:很多狀況要等執行時期,資料讀入或使用者輸入後才知道會有幾筆資料啊。
: 這些是編譯時期不會知道的啊。
: A:不會啊,都可以知道啊。
:
: 同上題,另一位回答道。
: A:方法? Q補充道:對,就是你會用哪一種資料結構或者是哪些現成的Class?
: A:用陣列啊。 Q可是陣列不能動態大小耶。
: A:是喔?......(沉默) Q:你都宣告一個很大的陣列來存放嗎?
: A:這也是個方法啦......(已經恍神中)
:
=========================================================================
: void fun(int* ptr)
: {
: ptr = new int[2];
: }
基本上出現這種用法, 或者說這個需求是所謂 variable size array 的問題.
我猜, 學校教的通常會強調使用已知固定大小的 n-dimension array 來事先
聲明, 這是因為不同語言對 n-維陣列 排法不同, 最安全辦法就是在 main
program 與 sub-program 間均宣告相同大小與型態的 n-維陣列, 使得下標
(index)的位址換算可以一致. 但做練習這樣是簡單可以的, 但要寫一個通用
讓別的 main program 都可以隨 varible size variable dimension 調用的
function sub-program 就有麻煩了.
老式的 FORTRAN 是在主程式預留最大的 array space , 讓 sub-program 用
call by address/reference 根據傳入的 dimension 自行換算成 one-dim
去取用.
在網路 message passing 時代, 使用 pointer 就比較麻煩一點, 但 c 語言
的低階功能就是能用 pointer 操控 address of mnemonic name , 所以多數
的花樣跟此有關.
如果照以前的 FORTRAN function 定義, function 帶入的參數, 依照數學習
慣是不可以在 function 處理時受到更動的, FORTRAN 因之也沒有調用自己的
recursive function 功能. function sub-program 如果用 stack space 暫
存 local variable 與傳遞參數, 上述問題就能一併提供, 但離開 function
sub-program 那些 function 內部的 local variable 就隨 return 可能就讓
stack 的再用增長而消失了, 因此一個臨時的 heap space 隨 malloc 動態配
置而來. 但要個空間並非就照那個大小剛好的給, 通常是有個基本最小單位,
常常是超用了, 或用了不收回也沒怎樣, 這就會養成壞習慣, 對分工發展各自
的 sub-program 帶來危害.
這種問題應該是給個範例, 每個要點都提到, 學習的人一次也就全通了.
不過, 讓 sub-program 來要求一個主程式也要使用到的 memory space , 在
可讀性與維護上是不好的示範.
: 面試到此已經快要升天了,針對一位強調自己會C++和物件導向的人再問道。
: Q:Class宣告中,你是如何決定成員的存取等級?
: A:存取等級?
: Q:就是 public, protected和private那三個啊,你宣告的變數或函式要放在哪一段裡面?
: A:喔,那個喔。那些比較理論的東西,我比較沒在注意(心虛中)
: Q:小姐,這些不是理論,這是物件導向最基本的精神,封裝。
: A:喔~那個喔,我都是改人家程式的,都是放在public。
: Q:所以你都不知道為甚麼要放在public嗎?
: A:恩......(無言)
:
: 另一位面試者,強調用MFC寫過Windows Application,所以問道。
: Q:你知道Windows Message的架構嗎?
: A:不知道(這個倒爽快)
: Q:你知道Procress和Thread的差異嗎?
: A:...(沉默是金)
: Q:在Windows裡面,不同Procress間要如何溝通?(我承認我蠢,連上一題都無法
: 回答的人,我還找死問這題!)
: A:阿!我有寫過,用CreatThread......
: Q:那是Thread,Thread和Process共用資料段,不需要啥特別的方法溝通。
: A:喔~(沉默)
======================
這一題的題例要扯 local/public 宣告還可, 但扯 multi-thread 就遠了一點 !
#include <stdio.h>
int * fun(int * ptr, int dim)
{
ptr = new int[dim + 1]; /* C array count from zero */
ptr[0] = ptr[0] + 100; /* 每次叫用 是否歸零或累加 */
ptr[3] = 3;
ptr[dim] = dim;
printf("%d %d %d %d %d\n",ptr[0],ptr[1],ptr[2],ptr[3],ptr[dim]);
return ptr ;
}
int void main() /* 新規範 結束時帶回shell是否正常結束指示,DOS 是 register A */
{
int * ptr, * temp1;
int asize, i ,j ;
asize = 12;
ptr = fun(ptr, asize);
ptr[1] = 1;
ptr[2] = 2;
for (i=0; i < asize - 5 ; i=i+5)
printf("%d %d %d %d %d\n", ptr[i],ptr[i+1],ptr[i+2],ptr[i+3],ptr[i+4]);
for (j=i; j <= asize; j++)
printf("%d ",ptr[j]);
printf("\n");
temp1 = ptr;
/* 老式的 gcc 2.X delete 又再 new 使用 data array 時,不會全 init to 0 */
// delete []ptr; /* delete ptr ; delete pointer with full array */
ptr = fun(ptr, 18);
delete []temp1; /*先要下一個 new array , 再清除舊的, 就不會用到舊的 */
printf("What happen ? ptr[0]= %d \n", ptr[0]);
return 0; /* depend on program exit for cli */
}
動態使用記憶體, 如果反覆 new delete 一個 array , delete 的反應
因效率的考慮, 隨下一個需求空間的大小會對宣稱該回收的資料有不同
的處理, delete 資料空間的回收反應, 在實作上跟語意有點差距.
◆ From: 140.115.4.12
推 avhacker:這篇最後的 code 是要比誰錯比較多嗎? 06/05 10:47
推 judo1127:一眼看到void main.....return 0 06/05 10:56
推 GregHowe:嗯...都宣告void ....還要return 0 ? 06/05 11:03
→ GregHowe:原po說multithread並不是以這題,而是另外提出,會錯意嗎? 06/05 11:05
推 GregHowe:這討論串的重點倒不是討論這題目的本身....而是一種現象 06/05 11:09
→ GregHowe:暫且不論這題是有多少錯誤..原po希望看到的是回答的內容 06/05 11:10
→ GregHowe:是否能看出一些比較像是程式設計師能看出的錯誤 06/05 11:12
推 clubflymf:原PO考的是基本觀念 有NEW 就有DELETE 不就這樣嗎?@@ 06/05 13:00
推 Cloud:這範例連delete都用錯了.... 06/05 13:39
推 achii:不懂就別自曝其短了...(搖頭) 06/05 20:16
→ ggg12345:有請各位高手指正!! 06/05 20:23
推 tyf99:前一個程式的最大問題是沒回傳ptr,main()的ptr一直都指null 06/05 20:30
推 tyf99:而你的new array最好改成struct,delete時直接砍掉struct 06/05 20:37
※ 編輯: ggg12345 來自: 140.115.4.12 (06/06 13:22)
推 Fenikso:都什麼年代了還在void main() 06/06 20:21
推 xsion:很多人都不知void main是錯的,甚至MSDN的範例也有void main 06/06 22:45
推 Fenikso:新資料都沒有吧..? 有的話也是vc6.0時代留下來的遺跡 06/06 22:57
推 swordsun:如果我沒記錯,g老師說話,連你們的主管都要乖乖聽 06/07 03:26
推 swordsun:g老師在講的, 跟你們在想的是兩碼子事 06/07 03:33
推 Fenikso:喔(挖鼻孔) 06/07 04:23
→ Fenikso:小弟愚昧無知 實在看不懂那比醬糊還不如的code想表達什麼. 06/07 04:23
推 bobhsiao:最前面的void fun(int* ptr);其實沒寫到main()的ptr 06/07 08:07
→ bobhsiao:後面的 QA 也沒寫這問題...這毛病我自己常犯所以印象深刻 06/07 08:07
推 Cloud:老師不是要授業解惑,怎麼搞的是我們幫他...... 06/07 08:22
※ 編輯: ggg12345 來自: 140.115.4.12 (06/07 08:51)
推 andymai:給個不一樣的觀念:老師不過是比較早學的人~老師不能犯錯? 06/07 08:45
推 Cloud:可惜這是網路...只能從打出來的字來判斷...XD 06/07 08:49
推 swordsun:只挑的出別人語法的錯,看不到人家考慮的問題 06/07 14:57
→ swordsun:猴子猴孫的智商, 一代不如一代 06/07 14:59
→ ggg12345:試了gcc4.0 delete後不會立即又被抓回來,但只清ptr[0]. 06/10 09:46
→ ggg12345:暫存pointer再用,delete的array其他的data仍然可以看得到 06/10 09:50