看了近来的论战, 我想对在校的大学生说。。。。。
首先声明,我写这个帖子,不希望任何人有人身攻击,脏活,刷屏等行为。我毕业3年多,专业机械设计,作了开发2年多,从今年开始也面试过很多人,尤其是这周,面过3个人。
袁锋和金旭亮的论战,我早就想说点1家之言,虽然我是非常支持袁,但是很多时候我们碰到问题的情形都是小马过河,在袁锋向来很简单的事情,但是对于在校大学生来说,实践起来,难度还是很大的,因为袁不做学生很久了,我想大概就记得学生时候做了哪些事情,做事的细节已经忘了,而我毕业没有多久,对我当学生的时候的情形记比较熟悉,
关于实践派,金是不折不扣地实践派,之所以很多同学支持,是因为金的实践的观点很能解决就业问题,金的方法是让学生尽量多写程序。金所在的学校是北京理工,碰巧我有个同事是北京理工的图形学博士, 我们没事的时候,他说起他在北京理工的时候,情况确实不是特别乐观,比如抄作业啊什么的,不过还好,也有非常优秀的。如果能在大学的时候认认真真的把课后习题做完,在机器上调试正确运行,,4年下来,智力一般的人,也能做个称职的程序员,为什么要抄作业那,抄作业的时候想着课程怎样怎样没用,毕业之后说起中国教育又是义愤填膺,这个时候为啥没有想起自己抄作业的时候了,如果学校聘请了不合格的老师,这是学校的失职,但是如果学生专业课抄作业,这就是学生的不对。我去年碰到过swap都写不出来的,据说还在上海找了个C++程序员的工作,这真是个疯狂的世界,他是这么写的
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
对于一个计算机专业毕业(一个南京末流重点)的人,写这样的程序,我想,他也是抄作业出来的。
我看到有人不支持袁,理由是这样,如果我们学了过多的理论,我们就没有时间写代码,没有时间写代码,什么都是空的
是的,不写代码,什么都是空的,但是你写的代码,能不能写点有深度的阿,很多同学热衷于考程序员等级考试,你们在学习的时候,能不能书上的代码都在机器上正确运行了,每个分支都跑到? 这样虽然花时间,但是绝对对你的工作能力有很大的保证,你工作的时候很多时候用不到高深的算法,但是一定会碰到逻辑比较复杂的情况,如果你没有写过足够多的代码,没有写过一些算法比较复杂的程序,是很难正确写出逻辑复杂的程序的。
好了,今天就说这么多。
问题点数:100、回复次数:163Top
1 楼jc15271149(奶皮儿)回复于 2006-12-02 10:26:17 得分 0
1Top
2 楼jc15271149(奶皮儿)回复于 2006-12-02 10:27:22 得分 0
2Top
3 楼jc15271149(奶皮儿)回复于 2006-12-02 10:27:27 得分 0
3Top
4 楼liangqingzhi(老之)回复于 2006-12-02 10:27:36 得分 0
4Top
5 楼liangqingzhi(老之)回复于 2006-12-02 10:27:43 得分 0
5Top
6 楼liangqingzhi(老之)回复于 2006-12-02 10:27:47 得分 0
6Top
7 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 10:52:00 得分 0
我靠,你们灌水太专业了!Top
8 楼julietcheng(努力提升自己,做个大气的女人)回复于 2006-12-02 11:00:42 得分 0
友情upTop
9 楼sdhylj(青锋-SS)(献血有益健康(别人的))回复于 2006-12-02 11:01:43 得分 0
upTop
10 楼zmx0506(风之伤)回复于 2006-12-02 11:15:06 得分 0
我还真是个菜鸟程序员
请问,楼主,那个swap(),怎么写才显得专业啊???
要我写,也大概就
void swap(void * a, void *b)
{
void * p = NULL;
ASSERT(a!= NULL && b!=NULL);
p = a;
a = b;
b = p;
}Top
11 楼dragonbbc(dragon)回复于 2006-12-02 11:21:49 得分 0
要灌就来专业的,呵呵Top
12 楼seu_cose(专注于通信技术)回复于 2006-12-02 11:34:51 得分 0
void swap(void * a, void *b)
{
void * p = NULL;
ASSERT(a!= NULL && b!=NULL);
p = a;
a = b;
b = p;
}
========================
这是什么?什么?Top
13 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 11:36:32 得分 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
专业不专业在于根本不能交换啊
int a, b;
a = 1;
b = 2;
swap(&a, &b);
用他的函数能交换a,b的value么?Top
14 楼seu_cose(专注于通信技术)回复于 2006-12-02 11:36:38 得分 0
一个南京末流重点
======================
莫不是说我们学校.....Top
15 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 11:37:04 得分 0
南京工业大学, 无意得罪Top
16 楼seu_cose(专注于通信技术)回复于 2006-12-02 11:38:58 得分 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
专业不专业在于根本不能交换啊
int a, b;
a = 1;
b = 2;
swap(&a, &b);
用他的函数能交换a,b的value么?
========================================
有些人C++基础没学好,忘记引用什么的了,他可能是个JAVA高手呢~~~~Top
17 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 11:42:09 得分 0
什么java高手,程序逻辑还没有搞清楚那,会不会写程序,我还是能够看的出来的
我面过至少20个人,Top
18 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 11:43:19 得分 0
这个是以前我在的一个破烂公司的同事,当时没把我气死
Top
19 楼FantasyNES()回复于 2006-12-02 11:46:52 得分 0
赫赫,搞笑Top
20 楼Bible_Chou(日子在发霉)回复于 2006-12-02 12:16:38 得分 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
void swap(void * a, void *b)
{
void * p = NULL;
ASSERT(a!= NULL && b!=NULL);
p = a;
a = b;
b = p;
}
// 企图通过传值改变形参来改变实参。
template<typename type>
void swap(type *a,type *b)
{
int temp = *a;
*a=*b;
*b = temp;
}
Top
21 楼Bible_Chou(日子在发霉)回复于 2006-12-02 12:17:49 得分 0
void swap(type *a,type *b)
{
type temp = *a;
*a=*b;
*b = temp;
}
Top
22 楼uhlanme()回复于 2006-12-02 12:29:37 得分 0
upTop
23 楼jxfengzi(子丰)回复于 2006-12-02 12:42:30 得分 0
方法一:交换指针
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
效果:速度快,函数看似正确,但一旦调用此函数,还是没有交换。原因还没想明白,请高手指点。
-------------------------------
方法2:交换值
void swap(int * a, int *b)
{
assert(a != NULL && b != NULL && "错误:参数不能为空指针");
int t;
t = *a;
*a = *b;
*b = t;
}
效果:值拷贝,速度慢,但结果正确。Top
24 楼jxfengzi(子丰)回复于 2006-12-02 12:44:49 得分 0
方法三:使用引用
void swap(int &a, int &b)
{
assert(a != NULL && b != NULL && "错误:参数不能为空指针");
int t = a;
a = b;
b = t;
}Top
25 楼jxfengzi(子丰)回复于 2006-12-02 12:45:42 得分 0
方法四:不使用中间变量,用运算代替交换。。。。。Top
26 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 15:52:31 得分 0
我的帖子怎么变成教学贴了?Top
27 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 16:54:50 得分 0
再顶一下
Top
28 楼zuoansuifeng(左岸)回复于 2006-12-02 16:57:57 得分 0
专业路过 ~~ 接分+帮顶~Top
29 楼believetruelove(C路艰辛)回复于 2006-12-02 17:21:43 得分 0
我觉得那个swap函数虽然看起来很简单,实际上能检验出一个人的编程基础吧.这也是大家对那个函数感兴趣的原因.
-----------------------------
to:jxfengzi
方法一不行是因为C的函数是值调用,传到函数中的数实际上是实参的副本,所以交换指针并没有改变原Top
30 楼believetruelove(C路艰辛)回复于 2006-12-02 17:26:47 得分 0
我觉得那个swap函数虽然看起来很简单,实际上能检验出一个人的编程基础吧.这也是大家对那个函数感兴趣的原因.
-----------------------------
to:jxfengzi
方法一不行是因为C中函数是值调用,传到函数中的数实际上是实参的副本,所以交换指针并没有改变原先a和b所指向的位置,交换a和b所指向内存单元的值才可以完成相应功能.
Top
31 楼zmx0506(风之伤)回复于 2006-12-02 17:45:50 得分 0
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
请问,这个函数 为什么错了呢?
我是说,你们说它是错的,用的什么编译器啊?反正我用的VC,好像还没出过错呢
请指点!!
还有,指针运算交换两个值,还可以用数学运算来实现么?看到楼上某位老兄在说,请教了Top
32 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 17:47:46 得分 0
我是说,你们说它是错的,用的什么编译器啊?反正我用的VC,好像还没出过错呢
==================
仔细看看咯, 很容易发现的问题
int a = 1;
int b = 2;
cout<<a<<','<<b<<endl;
swap(&a, &b);
cout<<a<<','<<b<<endl;Top
33 楼zmx0506(风之伤)回复于 2006-12-02 17:58:12 得分 0
今日得见高手,足慰平生了
小子我实在汗颜,大虾们别和我见识,我错了
believetruelove的见解令人毛塞顿开啊!!!!!
Top
34 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 18:02:05 得分 0
今日得见高手,足慰平生了
小子我实在汗颜,大虾们别和我见识,我错了
believetruelove的见解令人毛塞顿开啊!!!!!
============================
C常识而已Top
35 楼ccs02287(☆兜兜里有糖☆偶滴兜兜里有糖,你和我玩不?)回复于 2006-12-02 19:02:52 得分 0
大部分还是靠自己努力啊Top
36 楼zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果)回复于 2006-12-02 19:19:05 得分 0
我觉得最能体现编成功底的是写一个进制转换程序(就是十进制转二进制之类的东西)
得我刚学编程的时候
在那一个月内,将一个进制转换程序重写了十多篇
就此真正弄明白了整数类型与字符串类型有什么区别
而后,我不断发现该程序还有可改进的地方
最得意的一次是:
大三学接口技术时
老师要我们用汇编写一个将16位无符号数转成非压缩BCD码的程序
BCD码不就是十进制数嘛
于是我写了个任意进制转换程序(2~10进制),代码很简洁,不需要辅助存储空间(用一种很特别的方法处理反序问题的),而且效率很高
看看楼下的人能不能猜出这个程序是怎么写的Top
37 楼test33(隐姓埋名)回复于 2006-12-02 19:40:16 得分 0
看到脑壳大`
顶一个`Top
38 楼sevenzeal(I`m Pointer .Pointer is heart.So S=NULL)回复于 2006-12-02 19:52:54 得分 0
呵呵,原来这里也有很多~~~~大学C都没学好的啊
以前大一学C时期末考试你要是写出
void swap(void * a, void *b)
{
void * p = NULL;
ASSERT(a!= NULL && b!=NULL);
p = a;
a = b;
b = p;
}
这个,呵呵直接全卷零分,没听课啊(我们老师的话~~还不如不答)
Top
39 楼zhujiujun(<<<<<<<<动感光波>>>>>>>>)回复于 2006-12-02 20:11:59 得分 0
专业机械设计
呵呵~~~~~~~~~机械设计制造及其自动化
出来混,技术不是第一,做人是关键。
最近离职,公司居然招一个刚毕业的来接手。技术不行就算了,人品也不咋滴。
当初我没有人指导1-2周就看完的东西,现在那家伙半个多月了还什么都不懂。哎!Top
40 楼qq7338367(深秋小雨:让一切归于简单 快乐在指尖绽放)回复于 2006-12-02 20:15:05 得分 0
进制转换的呀?
我用VB写过一个..
可是很烂..唉.
想有时间的时候改一改,结果源代码丢了,那时候没电脑,存储在U盘上,结果我***********他********#$^$%#^#$%的大白鲨个破烂*********&^(*^#!$%^#$!%U盘..居然坏了.郁闷
过段时间再研究研究.用java写个.现在忙着做项目.Top
41 楼san_77227487()回复于 2006-12-02 20:35:26 得分 0
最得意的一次是:
大三学接口技术时
老师要我们用汇编写一个将16位无符号数转成非压缩BCD码的程序
BCD码不就是十进制数嘛
于是我写了个任意进制转换程序(2~10进制),代码很简洁,不需要辅助存储空间(用一种很特别的方法处理反序问题的),而且效率很高
看看楼下的人能不能猜出这个程序是怎么写的
========================================================
我大学时也做过,不过就很烂,用除法做。。。
最近工作了,用查表法做,快了很多。
不知道你有什么好办法呢,很想知道啊,别卖关子啦,呵呵Top
42 楼san_77227487()回复于 2006-12-02 20:37:00 得分 0
void swap(void * a, void *b)
{
void * p = NULL;
ASSERT(a!= NULL && b!=NULL);
p = a;
a = b;
b = p;
}
这个方法C就不知道行不行,但VC就肯定行。不过如果大家觉得不好的话,请详细点说出来啦Top
43 楼rongcanf(沉默是猪。)回复于 2006-12-02 20:45:23 得分 0
友情UpTop
44 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-02 20:50:21 得分 0
zhujiujun(<<<<<<<<动感光波>>>>>>>>) ( ) 信誉:100 Blog 2006-12-02 20:11:59 得分: 0
专业机械设计
呵呵~~~~~~~~~机械设计制造及其自动化
出来混,技术不是第一,做人是关键。
最近离职,公司居然招一个刚毕业的来接手。技术不行就算了,人品也不咋滴。
当初我没有人指导1-2周就看完的东西,现在那家伙半个多月了还什么都不懂。哎!
===========================
嘿嘿,我现在adesk上班,我相信不是因为我人好,adesk就让我过来上班吧Top
45 楼imneo()回复于 2006-12-02 21:00:49 得分 0
这个方法肯定不行!
不信自己可以去试试。
函数的参数在传入时会产生一个拷贝,这样做只是交换了拷贝的类容。交换了拷贝后指针的类容,而指针所指的类容并没有改变。Top
46 楼jxfengzi(子丰)回复于 2006-12-02 22:05:39 得分 0
回复人:believetruelove(C路艰辛) ( 一级(初级)) 信誉:100 2006-12-2 17:26:48 得分:0
?
我觉得那个swap函数虽然看起来很简单,实际上能检验出一个人的编程基础吧.这也是大家对那个函数感兴趣的原因.
-----------------------------
to:jxfengzi
方法一不行是因为C中函数是值调用,传到函数中的数实际上是实参的副本,所以交换指针并没有改变原先a和b所指向的位置,交换a和b所指向内存单元的值才可以完成相应功能.
-----------------------------------------------------------------------------
谢谢,我也想过可能只是交换了副本。
但副本在哪呢?
跟踪了一下,大概是调用函数时,参数入栈,
参数因为是指针,所以指针入栈,栈中存放a, b的地址,可以通过解引用*a,*b正确取a,b的值,
但函数swap中,交换的是栈中的变量,此时a, b的地址值并没有交换。
代码在VC6下编译:
// 1、通过交换指针,是不行的,因为指针存放在栈中,函数结束,栈被清空了。
void swap1(int * a, int * b)
{
assert(a != NULL && b != NULL && "错误:参数不能为空指针");
printf("swap : &a=%d, &b=%d\n", a, b); // 栈中值:a, b的地址
int * p = a;
a = b;
b = p;
printf("swap : &a=%d, &b=%d\n", a, b); // 成功交换栈中a, b的地址
} // 函数结束,栈被清空
// 2、通过解引用,交换指针指向的值,是可以的。
void swap2(int * a, int * b)
{
assert(a != NULL && b != NULL && "错误:参数不能为空指针");
printf("swap : a=%d, b=%d\n", *a, *b); // 栈中值:a, b的地址所指向的值
int t = *a;
*a = *b;
*b = t;
printf("swap : a=%d, b=%d\n", *a, *b); // 成功交换栈中a, b的地址所指向的值
} // 函数结束,栈被清空
// 3、我喜欢这种方法,如果用C++的话,应该采用模板
void swap3(int &a, int &b)
{
int t = a;
a = b;
b = t;
}
int main(int argc, char* argv[])
{
int a = 1;
int b = 2;
//////////////////////////////////////////////////////////////////////////
printf("\n第一次交换前:\n");
printf("&a=%d, &b=%d\n", &a, &b);
printf("a=%d, b=%d\n", a, b);
swap1(&a, &b);
printf("第一次交换后:\n"); // 参数为a, b 的地址,所以地址值入栈
printf("&a=%d, &b=%d\n", &a, &b); // 输出a, b的地址,还是原来的地址
printf("a=%d, b=%d\n", a, b); // 所以a,b的值依旧不变
//////////////////////////////////////////////////////////////////////////
printf("\n第二次交换前:\n");
printf("a=%d, b=%d\n", a, b);
swap2(&a, &b);
printf("第二次交换后:\n");
printf("a=%d, b=%d\n", a, b);
return 0;
}
Top
47 楼v41dugu(一步一生)回复于 2006-12-02 22:22:01 得分 0
方法一:交换指针
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
效果:速度快,函数看似正确,但一旦调用此函数,还是没有交换。原因还没想明白,请高手指点
//////////////////////////////////////////////////////
????? 看似正确??晕哦Top
48 楼hlq83(胡一刀)回复于 2006-12-02 22:38:04 得分 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
很明显不行,只是地址交换而已,指针所指向的内容不变。顺便说下,我是应届生!Top
49 楼hlq83(胡一刀)回复于 2006-12-02 22:43:37 得分 0
有两种解决方式 :
void myswap1(int * a, int *b)
{
int p ;
p = *a;
*a = *b;
*b = p;
}
void myswap2(int &a, int &b)
{
int p ;
p = a;
a = b;
b = p;
}
其实就是形参与实参的理解。Top
50 楼Jiana(Robin.English)回复于 2006-12-02 22:45:01 得分 0
方法一:交换指针
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
效果:速度快,函数看似正确,但一旦调用此函数,还是没有交换。原因还没想明白,请高手指点
//////////////////////////////////////////////////////
????? 看似正确??晕哦
///////////////////////是哦,翻翻c语言的课本吧!!很基础的。。
Top
51 楼Jiana(Robin.English)回复于 2006-12-02 22:46:28 得分 0
hlq83(胡一刀) ( ) 信誉:100 Blog 2006-12-02 22:38:04 得分: 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
很明显不行,只是地址交换而已,指针所指向的内容不变。顺便说下,我是应届生!
=====================晕哦!!!应届生呀!!!!
Top
52 楼hlq83(胡一刀)回复于 2006-12-02 22:56:24 得分 0
编译器调用函数1执行过程如下:
堆栈生成两临时变量,将a,b赋给他们,由于是指针变量。两临时变量和a,b指针的内存地址相同,函数内部执行过程中a,b的地方都换成了两临时变量,由于两临时变量与a,b值相同,指向的是相同的地址从而可完成值交换。
编译器调用函数2执行过程如下:
堆栈生成两临时变量,暂且定为temp1,temp2。程序执行过程如下:
int temp1 = &a;int temp2 = &b;
int p;
p = temp1;
temp1 = temp2;
temp2 = p;
a = temp1;
b = temp2;Top
53 楼hlq83(胡一刀)回复于 2006-12-02 22:58:14 得分 0
汇编语法忘了,翻译成汇编语言就很容易理解了。熟悉汇编的哥们写一下!Top
54 楼hlq83(胡一刀)回复于 2006-12-02 23:06:08 得分 0
工作了半年,没觉得自己比同事差,尤其是理论方面,觉得比他们欠缺的是:一些功能的实现需要什么函数找起来不是很熟练,可能要比他们花费更多的时间。Top
55 楼FarAwayFromHome()回复于 2006-12-02 23:23:41 得分 0
关键是要弄懂,什么是指针,什么是变量,什么是值引用,如果你学了汇编,或者学了C,再学Java或者别的什么,这些一切就都明白了,呵呵,欢迎各位有志之士加入程序讨论群:32998944(程序人生)共同探讨,更好的理解程序的内涵,共同进步!Top
56 楼jinti(重新做人)回复于 2006-12-02 23:55:17 得分 0
#include <algorithm>
std::swap
:DTop
57 楼gccr(古城痴人)回复于 2006-12-03 00:19:18 得分 0
第四种方法,谢谢! 我用Delphi,Java写程序嘀!!不过C仍是我最喜欢的语言,在大学里一直喜欢C来着,毕业后为了吃饭才改用Delphi和Java的.
void swep( int * a, int * b )
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}Top
58 楼mypandawz(游剑江湖)回复于 2006-12-03 01:31:14 得分 0
SWAP的考察是对C++中的引用,指针的指针,这些最基本的理解,应该属于基础范畴;
至于LS还有兄弟说这哥们可能是JAVA的好手,我不表示赞同,如果不能理解自己的代码是如何在OS中执行的,肯定也不是合格的程序员。
如LZ所说如果在学校里认真的去学习了专业课,独立的完成了后面的习题的话,我想这个错误就不会犯,所以也请那些抱怨袁老大观点太过的人仔细想想自己有没有在学校里扎好这些基础呢?是否用抄来应付课程,然后多余的时间去游戏了呢?
对于SWAP的值交换,LS的我也有一种方法,效率会更高点
void swap( int & a, int & b )
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
Top
59 楼lethe_qy()回复于 2006-12-03 01:36:17 得分 0
前面说的
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
int a = 1;
int b = 2;
cout<<a<<','<<b<<endl;
swap(&a, &b);
cout<<a<<','<<b<<endl;
为什么输出的都是1 2呢
Top
60 楼lethe_qy()回复于 2006-12-03 01:40:38 得分 0
前面说的
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
int a = 1;
int b = 2;
cout<<a<<','<<b<<endl;
swap(&a, &b);
cout<<a<<','<<b<<endl;
为什么错了呢Top
61 楼jxfengzi(子丰)回复于 2006-12-03 02:07:24 得分 0
第四种方法,谢谢! 我用Delphi,Java写程序嘀!!不过C仍是我最喜欢的语言,在大学里一直喜欢C来着,毕业后为了吃饭才改用Delphi和Java的.
void swep( int * a, int * b )
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
=========================================
int是几个字节?有没有考虑溢出?有符号数呢?无符号数呢?
用异或才是正道吧?Top
62 楼jxfengzi(子丰)回复于 2006-12-03 02:08:06 得分 0
to lethe_qy():
上面已经说了,请仔细看看。Top
63 楼FantasyNES()回复于 2006-12-03 08:13:38 得分 0
一个大学课后题目讨论的不亦乐乎......莫非都是搞Java的?Top
64 楼RjahtyYjfGB(大漠)回复于 2006-12-03 11:01:04 得分 0
一个大学课后题目讨论的不亦乐乎......莫非都是搞Java的?
什么意思?Top
65 楼vcmute(BCare4 H1Rest Good9!)回复于 2006-12-03 12:19:13 得分 0
目前为止,没有一个完全正确的Top
66 楼szliuy(仰天常笑)回复于 2006-12-03 12:57:16 得分 0
各位专业人士都是强人......
swap 确实是课堂练习,好久前研究过,俺只会一种写法,也只有一种解释方法......,
伤心中……。
#include<iostream.h>
void swap( int* , int* );
void main()
{
int a = 3 , b = 8 ;
cout<<"a = " << a << ", b = " << endl ;
swap( &a , &b ) ;
cout<<"After swapping... "<<endl ;
cout << "a = " << a << ", b = "<< b << endl ;
}
void swap( int *x ,int *y )
{
int temp = *x ;
* x = * y ;
* y = temp ;
}
栈
swap temp | 3 |
x | 0067:F090 |
__________y__|______0067:F092______|_____________
0067:F090 b | 8 |
0067:F092 a | 3 |
main | |
大家争论的swap写法及解释我怎么都看不懂啊......Top
67 楼qhdream()回复于 2006-12-03 13:08:13 得分 0
template<typename type>
swap(type &a,type &b)
{
a = a + b;
b = a - b;
a = a - b;
}
int main()
{
double i = 2.2;
double j = 3.3;
cout << "i=" << i << " j=" << j <<endl;
swap(i,j);
cout << "i=" << i << " j=" << j <<endl;
return 0;
}
、、当然只是演示,不够完善Top
68 楼qhdream()回复于 2006-12-03 13:12:15 得分 0
#include<iostream.h>
template<typename type>
void swap( type *x ,type *y )
{
type temp = *x ;
* x = * y ;
* y = temp ;
}
void main()
{
int a = 3 , b = 8 ;
cout<<"a = " << a << ", b = " << b << endl ;
swap( &a , &b ) ;
cout << "a = " << a << ", b = "<< b << endl ;
}Top
69 楼szliuy(仰天常笑)回复于 2006-12-03 13:25:39 得分 0
楼上写得更全......Top
70 楼dadi0189(冰雨)回复于 2006-12-03 14:35:15 得分 0
顶一下。Top
71 楼shenmea00000(学习中~~~)回复于 2006-12-03 15:02:03 得分 0
HEHE ,都跑题了Top
72 楼gzlyb(冰风)回复于 2006-12-03 16:00:50 得分 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
这个函数只能说存在重大缺陷
这样调用是错的:
int a = 1,b = 2;
swap(&a,&b);
这样调用用呢:
int *pa = new int(1);
int *pb = new int(2);
swap(pa,pb);
而且,如果a,b不是int,而是一个非常大的类呢?
在某些情况下,我喜欢下面这个函数的写法(当然,只有我用的情况下,如果给别人用就惨了...):
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
最恐怖的是如果是交换两个很大的类对象,而且很频繁,哪个的效率高?
具体情况具体分析Top
73 楼gzlyb(冰风)回复于 2006-12-03 16:06:42 得分 0
实际上应该这样:
void swap(type **a, type **b){
type *t = *a;
*a = *b;
*b = *t;
}Top
74 楼gwk2004()回复于 2006-12-03 16:31:37 得分 0
void swap(int *a, int *b){
int *t = a;
a = b;
b = t;
}
int c, d;
c = 1;
d = 2;
swap(&c, &d);
这里的c和d的地址传入swap中,a b指针分别指向c d,在swap中仅仅是使a指向d,b指向c 如
内容 地址
c:1 2000
d: 2 2002
a:2000 xxx(某值)
b:2002 xxx
交换完后仅仅是
c: 1 2000
d: 2 2002
a:2002 xxx
b:2000 xxx
而c,d的内容没有变化,a b是局部变量swap返回时a b就被释放了
void swap(int *a,int *b){
int *t;
t=a;
a=b;
b=t;
printf("%d %d",*a,*b);
}
int c, d;
c = 1;
d = 2;
swap(&c, &d);
printf("%d %d",c,d);
输出结果:2 1
1 2
这是我的一点点观点Top
75 楼seu_cose(专注于通信技术)回复于 2006-12-03 18:57:09 得分 0
技术帖????
==================
还有一个通过异或来交换值得Top
76 楼YuLimin(阿敏总司令:简单就是美—钻石闪闪您快结贴!)回复于 2006-12-03 19:18:29 得分 0
专业机械设计,跟我一个专业?:)Top
77 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-03 20:31:15 得分 0
嘿嘿,还是工程机械专业,你什么专业?
Top
78 楼xuwei(夕阳西下,断肠人在天涯)回复于 2006-12-03 22:15:52 得分 0
真会灌啊Top
79 楼flj01(峻岭)回复于 2006-12-03 23:18:11 得分 0
发个帖,证明我看过了。Top
80 楼yafizyh(亚斐)回复于 2006-12-04 02:21:38 得分 0
灌水都灌进脑袋里面去了。
接着灌吧,如果要交换指针,函数必须使用指向指针的指针。Top
81 楼yafizyh(亚斐)回复于 2006-12-04 02:26:28 得分 0
通过堆栈调用解析多线程
首先说明一下,堆是进程的全局数据内存存储区,栈是函数的局部数据内存存储区。由于大多数书籍在介绍堆或栈时,皆以堆栈泛指,因此,题目标题亦如此表述,希望读者不要混淆就是了。
要想编写出高性能的气象应用软件,多线程的使用是不可或缺的;要想全面深入理解多线程,必须对栈有十分清楚的理解。个人感觉在Windows编程中,栈的概念犹如C/C++中的指针,非常重要,但难于全面理解。市面上的书籍对堆栈的介绍或是蜻蜓点水、浮于表面;或是过于理论化,不够具体,不易理解。在这里,我以示例的形式将自己的一点学习体会写出来与大家分享。为了便于表述清楚,文章分为两部分:第一部分介绍函数栈的调用,这是此篇文章的核心。第二部分解析多线程的概念。
一、函数栈的调用
众所周知,在函数调用过程中,参数的传递是通过栈完成的,具体到机器码是什么样子呢?不同的调用约定(PASCAL约定或STDCALL约定等)将导致不同的参数压栈顺序,这些细节就略去不讲了,有兴趣的读者可以参考相关书目。为了把栈的概念表述清楚,这里将涉及到一些简单的汇编语言方面的知识,一点点而已。然后以一个简单的C++控制台程序为示例来进一步详细说明。先把代码列出来,够简单吧。
#include<iostream.h>
int fn(int n)
{
n+=1;
return n;
}
void main()
{
int i=1,j=10;
i=fn(i); // A
j=fn(j); // B
cout<<i<<" "<<j<<endl;
}
现在我们需要一点汇编方面的知识,以更好地了解栈是个什么东东。通俗一点讲,栈就是一块内存存储区,但是,这块内存存储区的操作使用有点特别。栈是由CPU直接管理的内存数组,CPU使用寄存器对其进行管理。ESP寄存器存放栈底(栈是向下增长的)数据的地址。push指令将数据压入栈中,ESP寄存器的值将随之减小;相反,pop指令将数据从栈底弹出,ESP寄存器的值随之增大。这样,ESP寄存器将始终存放栈底数据的地址。另一方面呢,CPU在执行代码的时候,完全是依靠CPU内部的寄存器完成的。通过EIP寄存器寻找当前要执行的代码,通过EBP、ESP定位函数参数的地址、函数局部变量地址,等等等等。
下面让我们看一下,当某一个函数被调用时,栈将有何变动。
(l)、函数参数被压入栈中。
(2)、返回地址(被调用函数执行完后将被执行的语句地址)被压入栈中,函数被调用,此时,CPU将准备执行函数体内的代码。
(3)、函数代码开始执行,首先执行的是将EBP压入栈中。
(4)、使EBP的值等于ESP。现在,EBP纪录的是当前栈底地址(ESP),以后函数就可以利用EBP对压栈的函数参数进行寻址了(此时已压栈的有函数参数、返回地址、EBP原始值,EBP+8即为最后压栈的参数地址)。
(5)、从ESP中减掉一定的数值,为函数留下局部变量空间。此后,ESP将用于局部变量的寻址。
编译器设计者的聪明才智真是令人敬佩。高级语言书写简单的一句函数调用,被编译成了如此繁杂的机器代码。
好了,下面我们再具体一点,以前面的C++程序为例,以VC反汇编断点调试的方式,看看以上过程是如何实现的。
在A处,进程的主线程调用了函数fn并传递了参数。其汇编代码如下:
004010B6 mov eax,dword ptr [ebp-4] //此时ebp=0x0012ff80,&i=0x12ff7c,ebp-4为i的地址
004010B9 push eax
004010BA call @ILT+20(fn) (00401019)
再明显不过了,第一行汇编代码将变量i的数值放入寄存器eax中。第二行汇编代码将变量i的数值压入栈中,对应前面(1)。第三行汇编代码执行call指令,此条指令自动将返回地址压入栈中,然后,跳转到函数体内部,准备执行函数内部的代码,对应前面(2)。
现在我们再来看看函数内部的代码是什么样子。这里只截取部分相关代码。
2: int fn(int n)
3: {
00401050 push ebp
00401051 mov ebp,esp
… … … …
4: n+=1;
00401068 mov eax,dword ptr [ebp+8] //此时ebp=0x12ff20 &n=0x12ff28 eax=1
0040106B add eax,1
0040106E mov dword ptr [ebp+8],eax
第一行汇编代码对应前面(3)。第二行汇编代码对应前面(4)。第三行汇编代码将变量n的数值放入寄存器eax中。第四行汇编代码将其加一。第五行汇编代码将结果放回变量n。这里可以十分清楚地看到,EBP寄存器用于参数的寻址。
现在我们再看看B处函数调用的情况。
004010C5 mov ecx,dword ptr [ebp-8] //此时ebp=0x12ff80,&j=0x12ff78 ,ebp-8为j的地址
004010C8 push ecx
004010C9 call @ILT+20(fn) (00401019)
可以看到,除了压栈数值变化以外,没有其它不同了。A处压栈i,B处压栈j。
下面使用VC单步调试,再来看函数体内部,汇编代码没有任何不同,不同的只是栈。当然了,函数体的代码是编译器一次性编译的。即使被多次调用,去完成不同的工作,不同的只是参数(调用栈),函数内部使用间接寻址,只是相同的机器码操作不同的内存存储区而已。
2: int fn(int n)
3: {
00401050 push ebp
00401051 mov ebp,esp
… … … …
4: n+=1;
00401068 mov eax,dword ptr [ebp+8] //此时ebp=0x12ff20 &n=0x12ff28 eax=10
0040106B add eax,1
0040106E mov dword ptr [ebp+8],eax
到了这里,栈的概念就讲完了。
二、解析多线程
这里首先要明确一点:每一个线程都独立拥有一个栈。
我们知道,Windows系统是一个多任务操作系统,多个线程可以“同时”执行。前面讲到,CPU执行程序代码完全依靠各种寄存器。当一个线程将被挂起时,当前的各种寄存器的数值就被存储在了线程的栈中。当CPU重新执行此线程时,将从栈中取出寄存器的数值,接着运行,好像这个线程从来就没有被打断过一样。正是因为每个线程都有一个独立的栈,使线程拥有了可以“闭门造车”的能力。只要将参数传递给线程的栈,CPU将担负起这块内存存储区的管理工作,并适时地执行线程函数代码对其进行操作,所有这一切与前面所讲述的没有不同。如果一个线程函数生成了多个线程,当系统在多个线程间切换时,CPU将执行相同的代码操作不同的栈。
下面举一个例子来加深理解。
随着面向对象编程方法的普及,我们很乐意将任何操作都包装成为一个类。线程函数也不例外,以静态函数的形式将线程函数放在类中是C++编程普遍使用的一种方法。通常情况下对象包括属性(类变量)与方法(类函数)。属性指明对象自身的性质,方法用于操作对象,改变它的属性。现在有一个小问题要注意了。类的静态函数只能访问类的静态变量,而静态变量是不属于单个对象的,他存放在进程的全局数据存储区。一般情况下,我们希望每个对象能够“独立”,也就是说,同一个类的多个对象能够各自干各自的工作,不要相互打扰。如果以通常的方法,以类(静态)变量存储对象的属性,可就要出问题了,因为类(静态)变量不属于单个对象。现在怎么办呢?如何继续保持每个对象的“独立性”。解决的方法就是使用栈,将参数传递给线程函数的局部变量(栈存储区),以单个对象管理每个线程,问题就解决了。当然了,解决方法是多种多样的,这里只是为了进一步解释多线程与对象的关系。
由于Windows的内部实现实在是太复杂了,这里只是在应用的层面上对栈给出解释。若深入到Windows内部,栈的定位首先需要依据寄存器SS经由(全局或局部)段描述符表得到相应的线性地址(虚拟地址)基址,此基址与ESP(函数局部变量寻址)或EBP(函数参数寻址)相加,然后再经由分页机制寻址物理内存。有兴趣的读者可以参阅文章后面的参考书目。一点学习体会写出来与大家分享,有不对的地方,欢迎指正。
参考书目:
《Intel汇编语言程序设计》(第四版),作者:Kip R.Irvine,电子工业出版社翻译出版。
《Windows环境下32位汇编语言程序设计》,作者:罗云彬,电子工业出版社出版。
Top
82 楼yafizyh(亚斐)回复于 2006-12-04 02:31:08 得分 0
都疯了Top
83 楼123ppmove(迷茫)回复于 2006-12-04 08:49:32 得分 0
markTop
84 楼wskyo(呆呆虫)回复于 2006-12-04 08:59:58 得分 0
汗Top
85 楼xinai0521(爱之风)回复于 2006-12-04 09:15:38 得分 0
void swap(int * a, int * b)
{
ASSERT(a!= NULL && b!=NULL && "错误:参数不能为空指针");
int * p = NULL;
p = a;
a = b;
b = p;
}
所谓指针传递,不过也一种值(这个值要特殊一点点)传递.所以他存在有值传递特一些特性.
所以到最后还是失败!
C,
C++引用就更特殊一些..~~:)Top
86 楼SBtoSB(凸( ̄_ ̄)凸SB公务员)回复于 2006-12-04 09:48:43 得分 0
RENYAOTop
87 楼huwei001982(凶猛的小狗)回复于 2006-12-04 10:02:42 得分 0
我晕, 想不到CSDN上还有这么多人写不出SWAP,无语啊Top
88 楼hanyufeng(寒雨丰)回复于 2006-12-04 10:14:21 得分 0
markTop
89 楼zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果)回复于 2006-12-04 10:22:18 得分 0
// 栈的定位首先需要依据寄存器SS经由(全局或局部)段描述符表得到相应的线性地址(虚拟地址)基址
在32位Windows下
CS、DS、SS、ES的基址都是0
进程空间保护靠的是分页机制
这就是所谓的平坦内存模式
FS的基址是当前线程的线程描述块
用户模式不使用GSTop
90 楼V_Grubby(帅的惊动了党中央)回复于 2006-12-04 10:24:23 得分 0
恩,学到不少东西!Top
91 楼fellowcheng(鹰击长空)回复于 2006-12-04 10:33:04 得分 0
有道理
我也是学机械出身,转行做程序的Top
92 楼greengrince(踏雪而行)回复于 2006-12-04 11:14:12 得分 0
gwk2004() 解释得很正确,指针传递不过是一种地址值传递,运算改变的是指向,但指向的内容是不会变的。而且还有形参的生存期问题。Top
93 楼dlyme(大老爷们儿)回复于 2006-12-04 11:17:24 得分 0
在一些国外计算机书上见到他们喜欢对指针进行传引用调用,好像我们很少这样用.
void swap(int* &a, int* &b)
{
int *p = NULL;
p = a;
a = b;
b = p;
}
void main()
{
int *a = new int(1);
int *b = new int(2);
cout<<*a<<" "<<*b<<endl;
swap(a, b);
cout<<*a<<" "<<*b<<endl;
}Top
94 楼hot886()回复于 2006-12-04 11:30:31 得分 0
学习Top
95 楼Qim(莫名-从星做起......)回复于 2006-12-04 12:07:49 得分 0
c#
private void swap(ref int a1,ref int a2)
{
int a = a2;
a2 = a1;
a1 = a;
}
vb.net
Private Sub swap(ByRef a1 As Integer, ByRef a2 As Integer)
Dim a As Integer = a2
a2 = a1
a1 = a
End SubTop
96 楼shibahu(人大代表)回复于 2006-12-04 12:10:59 得分 0
日 我还处于被面试的阶段Top
97 楼jian74566(风吹)回复于 2006-12-04 12:14:12 得分 0
我觉得袁金二人所针对的学生的层次是不一样的,金对的是理论只学到一点,缺少实践的学生,而袁说的直接已经有一定理论和实践基础后,应该以理论学习为主,而不是再去实践些没意义的程序Top
98 楼expter(Give to dream of a new height,My2007!)回复于 2006-12-04 13:13:49 得分 0
,,Top
99 楼codeworker999()回复于 2006-12-04 13:26:54 得分 0
讨论内容和题目怎么不符合-,-Top
100 楼xyq1986(综艺一哥)回复于 2006-12-04 14:27:42 得分 0
成swap() function 帖了Top
101 楼coowoo(coowoo)回复于 2006-12-04 15:06:46 得分 0
严重跑题!
顺便也跑一下题:要是有汇编基础根本不会写出这种东西来。Top
102 楼yafizyh(亚斐)回复于 2006-12-04 15:20:07 得分 0
zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果) ( ) 信誉:105 Blog 2006-12-04 10:22:18 得分: 0
// 栈的定位首先需要依据寄存器SS经由(全局或局部)段描述符表得到相应的线性地址(虚拟地址)基址
在32位Windows下
CS、DS、SS、ES的基址都是0
进程空间保护靠的是分页机制
这就是所谓的平坦内存模式
FS的基址是当前线程的线程描述块
用户模式不使用GS
----------------------------------------------------------------
正常启动Windows,使用VC6随便创建一个对话框项目,设置断点,寄存器数值如下:
其中CS = 001B DS = 0023 SS = 0023 ES = 0023 。
好恐怖,都不是0耶。一定是我的D版系统有问题^o^
EAX = 00000001 EBX = 00000000
ECX = 0012F658 EDX = 7FFE0304
ESI = 0012F670 EDI = 0012F6C0
EIP = 00401CBE ESP = 0012F670
EBP = 0012F6C0 EFL = 00000246 CS = 001B
DS = 0023 ES = 0023 SS = 0023 FS = 0038
GS = 0000 OV=0 UP=0 EI=1 PL=0 ZR=1 AC=0
PE=1 CY=0 ST0 = +0.00000000000000000e+0000
ST1 = +0.00000000000000000e+0000
ST2 = +0.00000000000000000e+0000
ST3 = +0.00000000001602540e+4628
ST4 = +0.00000000000000000e+0000
ST5 = +0.00000000000000000e+0000
ST6 = +1.49642966470388434e+4647
ST7 = +0.00000000000000000e+0000
CTRL = 027F STAT = 0120 TAGS = FFFF
EIP = 00000000 CS = 0000 DS = 0000
EDO = 00000000
Top
103 楼yafizyh(亚斐)回复于 2006-12-04 15:58:12 得分 0
奇怪了,竟然有这些个怪东西。
EIP = 00000000 CS = 0000 DS = 0000
EDO = 00000000
CS、DS又出现了一次,并且 EIP = 00000000 难道零地址处还有可执行代码?一般情况下PE文件的装载地址是0x0040 0000。
难道我的D版系统真的除了问题?
VC7再试一下。
EAX = 00000001 EBX = 00000000 ECX = 0012F504 EDX = 7FFE0304 ESI = 0012F51C
EDI = 0012F5F4 EIP = 004019F4 ESP = 0012F51C EBP = 0012F5F4 EFL = 00000246
CS = 001B DS = 0023 ES = 0023 SS = 0023 FS = 0038 GS = 0000
ST0 = +0.000000000068e-4933#DEN ST1 = +7.6425977006127817e-2505
ST2 = +1.563673475591e-4933#DEN ST3 = +0.0001621649522138e-4474
ST4 = +0.4506336555683590e-4932 ST5 = +0.4452285810052286e+3247
ST6 = +0.0000000076183653e-4256 ST7 = +0.003592695737e-4933#DEN
CTRL = 027F STAT = 0120 TAGS = FFFF
CS = 001B DS = 0023 ES = 0023 SS = 0023 还都不是0。
EIP也不是0了。还好,系统没问题。Top
104 楼sgnaw(李逍遥)回复于 2006-12-04 16:03:18 得分 0
一个简单交换函数引起的故事.Top
105 楼laoliu666(鹅鹅鹅,曲项向天歌,白毛浮绿水,红掌拨清波。)回复于 2006-12-04 16:44:08 得分 0
wTop
106 楼HappyQQ(黄金)回复于 2006-12-04 17:25:45 得分 0
世界上最笨的人莫过于此,
一个Swap函数就能够检验一个人的编程水平,那么写1000行的垃圾代码是否就证明那个人很强了?
兄弟,你也是搞开发的,你在开发过程中也经常犯一些错误,比如变量名类别定义错误,或者调用函数有误!不要以一个Swap函数来定义一个人的编程水平,说不定人家可以当你的“导师”了!Top
107 楼etop_lg(天外飞仙)回复于 2006-12-04 18:43:58 得分 0
写swap还要看是什么语言,楼主就是个搞C的,你考别人算法还差不多Top
108 楼yafizyh(亚斐)回复于 2006-12-04 21:54:11 得分 0
水都灌到脑袋里面了,接着灌呀!
swap函数的写法。
1、指针作为函数参数。
2、引用作为函数参数。
3、函数内部使用异或运算。
4、如果数不是很大,函数内部可以使用加减运算,雷同3。大数溢出就完蛋了。
下面再补充一个。
#include<iostream.h>
void Swap(int* a,int* b)
{
__asm{
mov eax, DWORD PTR [a];
mov ebx, DWORD PTR [b];
shr DWORD PTR [eax],1;
rcr DWORD PTR [ebx],1;
mov ecx,31;
L1: rcr DWORD PTR [eax],1;
rcr DWORD PTR [ebx],1;
loop L1;
rcr DWORD PTR [eax],1;
}
}
void main()
{
int c=0x12345678,d=0x89abcdef;
cout<<c<<" "<<d<<endl;
Swap(&c,&d);
cout<<c<<" "<<d<<endl;
}
楼下的接着补充啊!
疯狂的时代。Top
109 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-04 21:55:10 得分 0
写swap还要看是什么语言,楼主就是个搞C的,你考别人算法还差不多
=====================================
不是我面试别人的时候问的,是去年去了个垃圾单位,有个垃圾同事
问题是他写的是C++代码,你觉得这样像话么?
HappyQQ(黄金) ( ) 信誉:100 Blog 2006-12-04 17:25:45 得分: 0
世界上最笨的人莫过于此,
一个Swap函数就能够检验一个人的编程水平,那么写1000行的垃圾代码是否就证明那个人很强了?
兄弟,你也是搞开发的,你在开发过程中也经常犯一些错误,比如变量名类别定义错误,或者调用函数有误!不要以一个Swap函数来定义一个人的编程水平,说不定人家可以当你的“导师”了!
=======================================================================
少来,C程序员(做C开发)写不出Swap来,你觉得写过多少程序,没写过多少程序,对于
程序员来说,能掌握多少算法?
Top
110 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-04 21:57:21 得分 0
HappyQQ(黄金) ( ) 信誉:100 Blog 2006-12-04 17:25:45 得分: 0
世界上最笨的人莫过于此,
一个Swap函数就能够检验一个人的编程水平,那么写1000行的垃圾代码是否就证明那个人很强了?
兄弟,你也是搞开发的,你在开发过程中也经常犯一些错误,比如变量名类别定义错误,或者调用函数有误!不要以一个Swap函数来定义一个人的编程水平,说不定人家可以当你的“导师”了!
====================================
ok,我考一个题目
1000!阶乘最低非零位是多少?
5! = 120 最低非零位是 2
别虚晃一枪哦Top
111 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-04 22:05:57 得分 0
HappyQQ(黄金) ( ) 信誉:100 Blog 2006-12-04 17:25:45 得分: 0
世界上最笨的人莫过于此,
一个Swap函数就能够检验一个人的编程水平,那么写1000行的垃圾代码是否就证明那个人很强了?
兄弟,你也是搞开发的,你在开发过程中也经常犯一些错误,比如变量名类别定义错误,或者调用函数有误!不要以一个Swap函数来定义一个人的编程水平,说不定人家可以当你的“导师”了!
Top
etop_lg(天外飞仙) ( ) 信誉:100 Blog 2006-12-04 18:43:58 得分: 0
写swap还要看是什么语言,楼主就是个搞C的,你考别人算法还差不多
===========================================================
我说的那个哥们, 有段代码是这么写的,
T *pT = new T;
.....
pT = NULL;
delete pT;
你觉得这个换做你的同事会怎样?
今天当考官, 一个哥们试卷上面涂涂改改的写对了个一道题目,
今天面试他, 我让他把这道题目重新写一编, 没写对
其中有这么几行代码,
float pFloatArray = new float[size];
strcpy(pFloatArray, pAnotherFloatArray);
你觉得怎样,是不是开眼界了? 这个哥们上海某重点高校的应届研究生,Top
112 楼yafizyh(亚斐)回复于 2006-12-04 22:38:05 得分 0
LZ有点过激了,应该不是全部吧。
比如:
pT = NULL;
delete pT;
多好的编程习惯哪,删除指针前检查是否为空,删除指针后立即赋空值。
句柄也一样。只不过人家把位置颠倒了而已。
再如:
float pFloatArray = new float[size];
指针忘记加*号是常有的事^o^
编译一下就知道了,没什么大惊小怪的。
只要大的方向没问题,小毛病经过几个月的练习就可以避免了。Top
113 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-04 22:55:02 得分 0
pT = NULL;
delete pT;
多好的编程习惯哪,删除指针前检查是否为空,删除指针后立即赋空值。
句柄也一样。只不过人家把位置颠倒了而已。
====================================
我明确告诉他这个有问题,然后人家说没有问题,要是手误也就算了
但是他说没有错误,而且很固执
再如:
float pFloatArray = new float[size];
指针忘记加*号是常有的事^o^
=====================
这个*我忘了写,但是你没有看到后面的strcpy么?
strcpy怎么能够用哪?
他笔试卷子答对了, 黑板上面再写一编,就写不对,这个怎么说的过去?
Top
114 楼yafizyh(亚斐)回复于 2006-12-04 23:16:20 得分 0
再如:
float pFloatArray = new float[size];
指针忘记加*号是常有的事^o^
=====================
这个*我忘了写,但是你没有看到后面的strcpy么?
strcpy怎么能够用哪?
他笔试卷子答对了, 黑板上面再写一编,就写不对,这个怎么说的过去?
-----------------------------------------------------------------
没细看,还以为strcpy是自己写的函数,又觉得没有字节长度,感觉怪怪的。
卷子答对了, 黑板上面再写一编。为什么呢?难道他抄袭。也许人家太紧张了吧。Top
115 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2006-12-04 23:22:56 得分 0
没细看,还以为strcpy是自己写的函数,又觉得没有字节长度,感觉怪怪的。
卷子答对了, 黑板上面再写一编。为什么呢?难道他抄袭。也许人家太紧张了吧。
===============================================
没有那么紧张的, 这个题目我让他在黑板上面写了10分钟
一个应届硕士, 向量自己和自己叉乘的结果都不知道是什么,你觉得怎样?Top
116 楼yafizyh(亚斐)回复于 2006-12-04 23:23:53 得分 0
pT = NULL;
delete pT;
多好的编程习惯哪,删除指针前检查是否为空,删除指针后立即赋空值。
句柄也一样。只不过人家把位置颠倒了而已。
====================================
我明确告诉他这个有问题,然后人家说没有问题,要是手误也就算了
但是他说没有错误,而且很固执
--------------------------------------------------------------------
不是机试啊?如果是机试很容易发现的,“嘣”,一个对话框就出来的。
这个问题你也有份哪,给个程序让他自己写,写完跑出来看一下就行了。Top
117 楼yafizyh(亚斐)回复于 2006-12-04 23:33:36 得分 0
一个应届硕士, 向量自己和自己叉乘的结果都不知道是什么,你觉得怎样?
-----------------------------------------------------------------------
老实说,我也不知道。早忘掉了~_~
其实每个人都有他的长处,团体的力量正在与它聚集了所有人的优势。
正所谓,千里马常有而伯乐难寻。团体的力量是否能够发挥,领导者承担主要责任。Top
118 楼pankun(剑神一笑 Console下面干革命)回复于 2006-12-05 00:15:25 得分 0
// 栈的定位首先需要依据寄存器SS经由(全局或局部)段描述符表得到相应的线性地址(虚拟地址)基址
在32位Windows下
CS、DS、SS、ES的基址都是0
进程空间保护靠的是分页机制
这就是所谓的平坦内存模式
FS的基址是当前线程的线程描述块
用户模式不使用GS
-------------------------------------------
老兄,不是这样的
SS存的是段选择子,段选择子指向GDT或LDT中的段描述符,段描述符中的段基址+虚拟地址转换成线形地址,线形地址不开分页机制时就是物理地址,开分页机制时由对应的页表转换成物理地址.需求的页不存在于物理内存时引故障,页故障处理程序再申请物理页,从磁盘上把对应页表读入.你上面说的绝对有问题.
做开发学学保护模式的原理还是有必要的,至于上面一个swap还讨论...基础重要啊......Top
119 楼pankun(剑神一笑 Console下面干革命)回复于 2006-12-05 00:24:34 得分 0
回复人:yafizyh(亚斐) ( 二级(初级)) 信誉:100 2006-12-04 15:20:07 得分:0
?
正常启动Windows,使用VC6随便创建一个对话框项目,设置断点,寄存器数值如下:
其中CS = 001B DS = 0023 SS = 0023 ES = 0023 。
好恐怖,都不是0耶。一定是我的D版系统有问题^o^
------------------------------------------------
CS = 001B = 00011011 Index = 3, TI = 0, RPL = 3
指向GDT中索引3的描述符, 请求特权级3.很正常啊 :-)Top
120 楼zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果)回复于 2006-12-05 08:54:42 得分 0
// CS = 001B DS = 0023 ES = 0023 SS = 0023 还都不是0。
无语
你用SoftICE看看LDT中描述符的基址是多少
Top
121 楼zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果)回复于 2006-12-05 08:56:30 得分 0
现在越来越觉得理论与实践着两个词在中国变味了
实践:脱离原理搞应用
理论:只看理论书籍,不愿意拿SoftICE实际调试一下Windows系统Top
122 楼zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果)回复于 2006-12-05 09:03:40 得分 0
喔
上面有点小错误
“CS = 001B DS = 0023 ES = 0023 SS = 0023”表示描述符在GDT中
应该看GDT
我以前是在Win98中测试的
Win98应用程序的描述符在LDT中
NT没注意Top
123 楼zoologist(王朝)回复于 2006-12-05 09:09:41 得分 0
怎么都打算用最简单的方法解决简单的问题呢?Top
124 楼zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果)回复于 2006-12-05 09:30:42 得分 0
Windows XP Professional SP2 的测试结果:
CS=001B, DS=0023, SS=0023, ES=0023, FS=003B, GS=0000
GDT:
...
001B Code32 00000000 FFFFFFFF 3 P RE
0023 Data32 00000000 FFFFFFFF 3 P RW
...
003B Data32 7FFDD000 00000FFF 3 P RW
...
Top
125 楼hailongchang(什么时候才能看到星星啊。。。)回复于 2006-12-05 09:31:00 得分 0
We are not discussing the details of swap function!Top

