看板Programming
标 题Re: TC++ 变数视野求教
发信站Giga News Service (Fri Feb 29 07:05:18 2008)
转信站ptt!ctu-reader!ctu-gate!news.nctu!news.ccu!Yuntech-News!csnews.cs.nctu
MSGID: 0:0/0 385D0290
-KEY: F6E82AE0
>int func1(void)
>{
> int i;
> :
> :
> return i;
>}
>
>int i;
>
>void func2(void)
>{
> :
>}
----------------------------------------------------------------------
由於回文的高手有好几位,
而各位回文时引出的引言很长,
所以将各位的文整理一下一并在此回了,
恳请见谅.
----------------------------------------------------------------------
From:
[email protected] (㊣金大支大寿,六六大支!)
>※ 引述《
[email protected] (marujoung)》之铭言:
>> 我知道本板的高手很多,
>> 为什麽都保持沉默呢? 我已等了近两个月了...
>
>你讲得太简单,
>依照你提供的架构仿写程式,无法复制错误,
>当然也就无法帮你解释错误何在。
>
>简单的想法是TC++或许有bug,你可换用Dev-CPP重新编译试试。
TC++ 确实 bug 很多, 但要我换 compiler....(面有难色)
这就好像开了十几年的老爷车问题很多, 它的问题只有我知道,
而我也习惯爆出问题时该如何因应了, 例如打颗蛋到水箱,
今天换台劳斯莱斯,
很棒! 但故障时我就不会修理了...
除了 TC++ 外 C compiler 我用 BCB,
但为何本程式坚持用 TC++ 呢?
因为程式中有拦截硬体中断的动作, 而 BCB 不让我这麽做.
----------------------------------------------------------------------
From:
[email protected] (五黑)
>1. 别人不见得学过所谓 "大拇指原则"
所谓大拇指原则, 就是函式内容以一页为原则.
>2. 为什麽你会猜测是func1把区域变数i当作全域变数使用? 凭什麽说违反视野?
大哥! 我从头到尾都没这样说喔! 烦再阅前文,
我只是移动了一下 int i 的位置就解决了,
so 好像是在视野的使用上出了问题...
我好像找到解释的理由了, 烦见信尾.
>3. 出错,错误讯息讲什麽,指向哪一行,看清楚了在做除错动作.
大哥! 小弟我是真的有难题要求助, 不是来吵架的, 干嘛讲话那麽冲!
小弟向来以除错技术佳自豪, 这回抓不出原因是学艺不精, 对视野了解不够.
compiler 根本说没错, 是执行结果不是我想的.
>或许你可以把全域变数i移到最前面,但也别删掉func1内的区域变数i.
但事实是我改成这麽做後问题就解决了耶?
仔细品味兄台这句话,
猜想兄台的想法是外在变数在进入 func1 前作用了,
但一进入 func1 便被 auto 变数遮盖,
离开 func1 进入 func2 时 i 又变回外在变数, 是吧?
噫! 好像有道理喔! 可是我不敢再试,
因目标(资料库)太大无法备份, 再出状况会很麻烦.
而我的想法(拿掉 auto)是:
func1 及 func2 统一共用外在变数 int i,
由名称叫 i 而非有意义的单字便知它只是个暂用的变数, 例如回圈.
当 i 离开 func1 时它的值是什麽已不重要,
因为进入 func2 时值会重设,
同理当 i 离开 func2 时它的值是什麽不重要,
因为再进入 func1 时值会重设.
结论: 也许 bug 真的被您抓到了, 但很冒险, 我不敢试;
我的想法很简单, 但较安全, 且通过了事实证明.
也许您会问: 既然坚持自己的想法, 干嘛问我们!
程式的 bug 已用我的方式解决了, 小弟我只是想知道当初错误的原因.
----------------------------------------------------------------------
From:
[email protected] (那里没有汤匙)
>不是高手保持沉默,而是他们没办法回答你的问题。
>因为你的问题比较像是 dependency on compiler / os。
>已经是高手等级的人,
>当菜鸟练功时用的 TC 版本大多为 2.01 左右,也就是十余年前。
>而且现在多半已经不用 TC 了,
>因此无法复制你的 bug,自然无法回答你的问题。
>
>: 期间我把施大师的着作拿出来 k 了,
>: 疑惑仍在:
>: func1 内的 int i 是在执行时以堆叠配置,
>: 而夹在 func1 和 func2 间的 int i 早在编译时就配置好了,
>
>我大概有十年以上没碰 TC,当然我并不是高手,
>但在我印象中 borland 的 compiler 对变数会分已初始化跟未初始化的资料,
>分别置放在 BSS 与 DATA 节区,而你的 i 都是属於未初始化的资料。
>如果我没记错,在 Boralnd C Compiler 的 memory model 中,
>small 的 bss, data 跟 stack 好像是在一起的。
>我猜你大概是用 tiny 或 small 的 memory model。
>你有没有试过改用 large 来 compiler?
呵您猜错了, 本程式只能用 huge 编译, 因为 DATA 段太大了,
大到我原本超过 64K, 但 compiler 不让我这麽用,
我只好拼命减肥使 DATA 小於 64K --
说到这里,
坊间(十几年前啦)的书都说 huge 的 DATA 段可超过 64K,
但我的经验是六种 model 都不能超过 64K,
於是我编译的习惯是:
若要写成 *.com 用 tiny 模式,
小程式用内定的 small,
大程式则实验一下,
拿本程式来说, large model 也能过关, 但实际下去跑时就会出错
>或者观察 compiler 出来之後各变数的置放方式?
>: 两者在 RAM 中的位置并不相同, 应该不会干扰才对啊?
>我只能说你太武断了,为什麽不把整个 memory map 弄出来看呢?
抱歉小弟才疏学浅, 这招我就不会了, ^^"
debug -T ? :P
我知道有这种工具, 但我手边没有.
----------------------------------------------------------------------
From:
[email protected] (sjgau)
>: 我知道本板的高手很多,
>: 为什麽都保持沉默呢? 我已等了近两个月了...
>: 期间我把施大师的着作拿出来 k 了,
>: 疑惑仍在:
>你的问题没有得到回覆,除了你没有po 完整的程式,
>比较不容易知道你的问题在哪里之外,
>问问题的技巧 也是很重要。
>
>问对问题之後,一切就好办。
我没 po 文除了原始程式大过 64K 外,
很多列的列长超过 80 bytes, 你叫我怎麽贴!?
这个程式是用来筛选资料库中的某些不良资料,
数年前所写, 运作良好,
近日为了强化一项功能时发现程式太乱自己都看不懂当年是怎麽想的,
於是开始将之「大拇指原则」化,
如 func2 就切割成十几个函式;
本来 func1 和 func2 各有一个 auto 变数 int i 互不干扰,
现在 func2 被切割了, 它的 int i 势必升级为外在变数,
於是将之放在 func1 後 func2 前,
结果出差错了: 某些资料类别全部被砍!
**********************************************************************
关於程式错误的原因, (是不是我不知道喔)我是这麽解释:
依施威铭大师的分类, 长得最像的写法是:
func1 内的 i 应写为 extern int i
理由是 func1 和 func2 间的那个 int i 是「定义」不是「宣告」,
书中曾提过我这种写法的变数名称若相同会干扰(我忘了在哪一页看到的)
func1 内写 int i 是企图在外在变数 int i 视野之前使用後者,
所以应该是个「宣告」; 既然是宣告就该加上 extern.
於是, 本程式的写法是种妾身未明的写法,
compiler 分不清它是「宣告」还是「定义」,
也许不同的 c compiler 处理方式不同,
TC++ 选择放它过关, 但後果自负.
而我的改法,
即把 func1 内的 int i 去掉, 外在变数 int i 移到 func1 前,
因为该处前面的函式都没叫用 int i,
而该处後面的函式知道 i 是共用的,
避开了抢饭碗的情形, 所以就执行对了.
--- 本站可传档、聊天、写信喔 !
* Origin: 翡翠王国资讯站(BBS) [站址: 203.204.191.217] (0:0/0)