作者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
1F:推 avhacker:这篇最後的 code 是要比谁错比较多吗? 06/05 10:47
2F:推 judo1127:一眼看到void main.....return 0 06/05 10:56
3F:推 GregHowe:嗯...都宣告void ....还要return 0 ? 06/05 11:03
4F:→ GregHowe:原po说multithread并不是以这题,而是另外提出,会错意吗? 06/05 11:05
5F:推 GregHowe:这讨论串的重点倒不是讨论这题目的本身....而是一种现象 06/05 11:09
6F:→ GregHowe:暂且不论这题是有多少错误..原po希望看到的是回答的内容 06/05 11:10
7F:→ GregHowe:是否能看出一些比较像是程式设计师能看出的错误 06/05 11:12
8F:推 clubflymf:原PO考的是基本观念 有NEW 就有DELETE 不就这样吗?@@ 06/05 13:00
9F:推 Cloud:这范例连delete都用错了.... 06/05 13:39
10F:推 achii:不懂就别自曝其短了...(摇头) 06/05 20:16
11F:→ ggg12345:有请各位高手指正!! 06/05 20:23
12F:推 tyf99:前一个程式的最大问题是没回传ptr,main()的ptr一直都指null 06/05 20:30
13F:推 tyf99:而你的new array最好改成struct,delete时直接砍掉struct 06/05 20:37
※ 编辑: ggg12345 来自: 140.115.4.12 (06/06 13:22)
14F:推 Fenikso:都什麽年代了还在void main() 06/06 20:21
15F:推 xsion:很多人都不知void main是错的,甚至MSDN的范例也有void main 06/06 22:45
16F:推 Fenikso:新资料都没有吧..? 有的话也是vc6.0时代留下来的遗迹 06/06 22:57
17F:推 swordsun:如果我没记错,g老师说话,连你们的主管都要乖乖听 06/07 03:26
18F:推 swordsun:g老师在讲的, 跟你们在想的是两码子事 06/07 03:33
19F:推 Fenikso:喔(挖鼻孔) 06/07 04:23
20F:→ Fenikso:小弟愚昧无知 实在看不懂那比酱糊还不如的code想表达什麽. 06/07 04:23
21F:推 bobhsiao:最前面的void fun(int* ptr);其实没写到main()的ptr 06/07 08:07
22F:→ bobhsiao:後面的 QA 也没写这问题...这毛病我自己常犯所以印象深刻 06/07 08:07
23F:推 Cloud:老师不是要授业解惑,怎麽搞的是我们帮他...... 06/07 08:22
※ 编辑: ggg12345 来自: 140.115.4.12 (06/07 08:51)
24F:推 andymai:给个不一样的观念:老师不过是比较早学的人~老师不能犯错? 06/07 08:45
25F:推 Cloud:可惜这是网路...只能从打出来的字来判断...XD 06/07 08:49
26F:推 swordsun:只挑的出别人语法的错,看不到人家考虑的问题 06/07 14:57
27F:→ swordsun:猴子猴孙的智商, 一代不如一代 06/07 14:59
28F:→ ggg12345:试了gcc4.0 delete後不会立即又被抓回来,但只清ptr[0]. 06/10 09:46
29F:→ ggg12345:暂存pointer再用,delete的array其他的data仍然可以看得到 06/10 09:50