打印

难道我发现了Keil的BUG?请各位高手看一看——有图有真相

[复制链接]
楼主: XIANSir
手机看帖
扫描二维码
随时随地手机跟帖
101
XIANSir|  楼主 | 2011-3-2 11:45 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
21IC的工程师们果然都很热心啊!!我来对地方了:lol

使用特权

评论回复
102
RyanHsuing| | 2011-3-2 14:44 | 只看该作者
谢谢大家给我上了课!

使用特权

评论回复
103
刘前辈| | 2011-3-2 16:52 | 只看该作者

使用特权

评论回复
104
XIANSir|  楼主 | 2011-3-2 17:23 | 只看该作者
103# 刘前辈
谢谢,我知道错了!!!!!

使用特权

评论回复
105
highgear| | 2011-3-2 22:35 | 只看该作者
顶 123jj, 对技术理解非常到位。 bit 类型关键字在很多嵌入式 compiler 里使用, 不足为奇。

首先, 刘工的 "标准ANSI C 这么写,是为了方便以后移植"的概念是不对的, bit field 从来就不是为移植准备的, 这点是公认的。

其次, 关于所谓“提升”, 这只是编译器从效率角度出发, 把某些变量用最简单,最高效率的方式实现(这就是精通汇编的另一个好处), 就是说提升到最优方式。51有位处理器, 所以 1 位(仅仅是 1位) bit field 可以用位处理器实现, 但也有很多的处理器没有位处理器,只能用 byte, int 等用位处理(&|~^)的方式实现。所以楼主的“提升”部分上是正确的。其实compiler 也是人做出来的, 有些时候, 会考虑到程序员的境况, 例如:
     int x;
     if ((x & 0x8000) != 0)     有些编译器会编译出仅仅两条汇编指令,1条位测试, 1条跳转。


很多嵌入式程序员最容易犯的错误就是位处理与逻辑处理, && 两端的类型是 bool,变量可以不同。0xFF&& 0xFE实际上是 0xFF != 0 && 0xFE != 0 的简写。  

LZ是不是给我们讲讲你是如何把一个&&运算符两边的bool类型提升/转换为char类型的?这是咱们中国人的创新,一定要好好证明一下”, 刘工本性不改。 51 有位处理器, 所以对于 bool 类型不用 byte, int 运算。但其他的无位处理器的 cpu 的 bool 运算用 byte (8bit cpu), int16(16-bit), int32(32bit cpu)等处理和存储。这是编译器的本质, 用不着什么创新。 用 0 和非 0 来表示 bool 是很自然的事情, 毕竟基本上 cpu 都有这种判断指令。 多说一句 , visual basic 是用负 和 非负 表示逻辑。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
123jj + 1
106
123jj| | 2011-3-3 07:30 | 只看该作者
谢谢highgear老师给俺们菜鸟上课,不魁为C高手中的高手,讲解的非常深刻到位,俺学习了。

使用特权

评论回复
107
ayb_ice| | 2011-3-3 08:21 | 只看该作者
105L
这下刘前辈又不高兴了

使用特权

评论回复
108
刘前辈| | 2011-3-3 10:23 | 只看该作者
“LZ是不是给我们讲讲你是如何把一个&&运算符两边的bool类型提升/转换为char类型的?这是咱们中国人的创新,一定要好好证明一下”。


谁看不出前辈这句话的弦外之音?“咱们在C标准方面有过创新吗?”逗!所长你把bool 类型可以有“部分提升”的C标准文本最好像我那样贴出来,别在这“凭空创新C标准”。在你说什么“部分提升”之前,“一定要好好证明一下。”——拿出证据来再说话。你不是会查互联网吗。查呀……
        否则,就别在这大忽悠!

最好像我这样,举个例子:
   pin.b_4=!(pin.b_1) && (123*321 );
(123*321)括号里的运算当然不是逻辑运算,*  两边的操作数(当然不是bool类型)是经过整提升之后再相*的,(神马“部分提升”,所长就喜欢创新概念。)运算结果等于int 39483,bool 值等于TRUE。(经试验,编译器在预编译阶段就算好了,直接取bool 值=1。

然后推论: pin.b_4=!(pin.b_1) && ( pin.b_2*123 );
        
         所长要说这个右边逻辑分量 (pin.b_2*123 )存在部分提升,前辈还真没话说。可惜,所长大人是拿123jj 的式子举例的:
      pin.t_4 = ((~(bit)pin.b_1) && (~(bit)pin.b_2));

       这里的左右逻辑分量中没有算术运算符;连算数操作数都没有,你提升谁?一个普通数123 ,你没事干提升到int ? 好玩?                     

前辈说的是逻辑运算符 && 两边的bool 类型逻辑分量没有整提升的问题(概念);——别创新概念。

所长偏要创新概念,显得他更高明“你说错啦,……”   所长说的是在 a &&(x * y )式中,bool 逻辑分量(x*y ) 存在整提升。——请举个例子看看。

哈!逻辑分量(x * y )=TRUE;  你还提升个啥?
学了一辈子C,C++,C# ,这么点概念还搞不清。

         顶 123jj, 对技术理解非常到位。 bit 类型关键字在很多嵌入式 compiler 里使用, 不足为奇。


所长真逗,再好好看看96楼说的是什么意思。


所以,强调一句:LZ的指令系统没有 bit 类型。那么123jj下面的强制(bit)类型有什么意义?没这个关键字,连编译都通不过,更别说LZ的方便移植初衷了:(要不你定义一个 typedef    bit   char  ; )
   pin.t_4 = ((~(bit)pin.b_1) && (~(bit)pin.b_2));

另一方面,如果这个C 能够处理bit 变量,这个问题还要做吗?
bit  pin.b_1;
bit  pin.b_2;
bit  pin.b_3;
……
……

或者:
bdata  pin;
sbit  pin.b_1=pin^0;
sbit  pin.b_2=pin^1;
sbit  pin.b_3=pin^2;
……
……


       LZ一开始就告诉你了,我将来要移植的那个处理器可能没有(bit)逻辑处理器。——所以我才按标准C这么写 ,以便将来移植。

          所长在这装聪明:“你不用这么写,很多(不是大多数?不是所有?)嵌入式编译器里都有bit 类型操作。”

       废话,别人都不知道?别人都没做过调研,就所长知道很多编译器都有,不仅C51有。——就所长聪明。
  
        LZ当时开发的时候用的就不是C51吧?就没有bit 类型处理吧?

        


使用特权

评论回复
109
highgear| | 2011-3-3 22:54 | 只看该作者
这个bool 问题,明显还是刘工概念不清。

很简单, && 两边必须是逻辑表达式逻辑分量,这个词并不确切(估计刘工又要 @#¥@%# 了, 呵呵)。pin.b_2×123 也好, 0xFF 也好,都是被归为逻辑表达式,虽然表达式中的 == 与 != 可以被省略, 看上去以为是 byte, int 类型, 估计这让刘工产生了错觉。除了 51 之类具有位处理器的 cpu 外,其他cpu compiler 的 bool 类型并非元数据类型,cpu 中并没有1位的存储形式,bool 是用byte(8bit cpu), 16/32bit int(16/32 cpu, 例如 80x86) 实现的。因此,在复杂的逻辑表达式中, 例如 pc 中,byte 形式的逻辑表达会以 32bit int 的 bool 作为中间存储过程(false : 0x00000000, true: 0xFFFFFFFF, vb 则恰好相反, 用 vc++做vb控件时很讨厌 )。同样, 即使 1位的 bit field 在这样的无位处理器 compiler 里, 也还是 byte, int 的处理形式。

使用特权

评论回复
110
itelectron| | 2011-3-4 08:32 | 只看该作者
原来 农民讲习所==highgear 呵呵!

使用特权

评论回复
111
ayb_ice| | 2011-3-4 08:32 | 只看该作者
大家没有必要咬文嚼字的,意思都差不多,同样的英文,翻译可能还不同呢,这在C,C++里还是比较常见的,
我相信大家都知道怎么解决这个问题了,
首先要确保程序格式规范准确,否则问题就不那个问题了
我经常说的一句“正确的现象只有一个,错误的现象千奇百怪”

使用特权

评论回复
112
刘前辈| | 2011-3-4 10:20 | 只看该作者
123jj 高论:对位域变量(char型)求反,必须加入强制数据类型(bit型)转换,否则出错。 如:
    pin.t_4 = ((~(bit)pin.b_1) && (~(bit)pin.b_2));

所长关照:顶 123jj, 对技术理解非常到位。 bit 类型关键字在很多嵌入式 compiler 里使用, 不足为奇。



哈!所长果然对技术理解非常到位。&&两边的bool 类型,无论
是bit / char / int / long,都是一样的! 根本不需要强制类型转换!
举例: bit && char ;  char && int ;   int && bit ;  都是正确的!



“否则出错”——“对技术的理解非常到位。”讨好mm太过了吧……


前辈不敢恭维。前辈所有讲的东西都是书上来的,有证可查的。

使用特权

评论回复
113
刘前辈| | 2011-3-4 10:57 | 只看该作者
还有3个实验结果。

使用特权

评论回复
114
123jj| | 2011-3-4 19:44 | 只看该作者
呵呵,本来那个贴子,俺淘淘浆糊淘的满开心的,跟在二姨家的高人后面捡点菜,学点**毛蒜皮小本事,结果,怎么俺成了主角,成了砖头渣子横砸的对象? :L

请刘前辈刘大师刘大人别计小人过,俺一再声明,俺不搞技术也不做电工,C语言中,常用的几十个基本关键词俺都写不全,只能说大概了解一下C语言,根本没有高论可言,所有的发言除了灌水,均来自于网上其他网友的发言及思想,现搬现抄罢了。

刘大师找俺PK,有失刘大师高大威武的形象,真正的高手是你们,象刘前辈刘大师刘大人这类的高手奇人,武功盖世,绝顶聪明,请刘前辈刘大师刘大人别计小人过,如有得罪,请高抬贵手~~~

对刘大师112楼的发言,小辈有一点不解?大师言:"无论JNC/JZ, 都是测试bool做FALSE! 一样!”

俺尽管C语言不懂,和大师根本没法比,但汇编还是略为能看懂一二,大师所圈的实例,明摆着,前面一个是对bool位求反作测试,判断其值是TRUE或FALSE,如是FALSE则跳转,是TRUE则不跳转。
而后面一个是对char字节作测试,由于前面有这两条指令,ANL  A,#01H, CPL  A, 则ACC的值永远是非0值,对ACC的测试0判断结果永远不跳转!

俺的水平实在太差劲,实在无法理解大师的解说:"无论JNC/JZ, 都是测试bool做FALSE! 一样!”请大师能在百忙当中抽点时间出来,再来指点一下俺们菜鸟~~~

1.jpg (148.69 KB )

1.jpg

使用特权

评论回复
115
594364676| | 2011-3-4 21:48 | 只看该作者
21IC真的可以和凤凰网学学。

使用特权

评论回复
116
highgear| | 2011-3-4 22:17 | 只看该作者
顶114楼的 123jj, 解释的非常到位,同时也可以看出刘工的对技术的理解不够。

“JNC/JZ, 都是测试bool做FALSE”, 这样可笑的理解,就不予评论了。

使用特权

评论回复
117
icecut| | 2011-3-4 22:37 | 只看该作者
多看keil的help手册,keil根本就不是标准c

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
123jj + 1
118
123jj| | 2011-3-5 07:11 | 只看该作者
icecut老师正解!

keil只是标准C的一个子集。

使用特权

评论回复
119
刘前辈| | 2011-3-5 13:16 | 只看该作者
本帖最后由 刘前辈 于 2011-3-5 13:22 编辑

同意117楼。任何C都是以ANSI C为蓝本的,有标准可以互相移植呀。ANSI C 以外的编译器内容都属于自身的扩展,——不可互相移植。 所以,C51中的 bit 类型,是C51中的扩展类型,往哪移植都不行! GCC,ARM C都没有bit 类型。“C超高手”说C51中 bit 与移植无关,噢,——大概是说uc/OS移植到51单片机这种研究。LZ说的是这个程序要移植到AVR或者其他非51单片机这种研究。——南辕北辙。

使用特权

评论回复
120
XIANSir|  楼主 | 2011-3-5 13:20 | 只看该作者
本帖最后由 XIANSir 于 2011-3-5 13:28 编辑

本来上面都是大侠在说话,我这初来乍到小屁孩是没有资格说话的,可是呢:我对上面那段程序在ARM是如何执行的很感兴趣——毕竟以后肯定要转向ARM的,那样才显得“更牛X”呀,呵呵:lol只贴现象,不敢发表评论:











另外,123jj前辈在114楼问刘前辈的那个问题其实刘前辈前面已经跟小辈俺解释过了:因为定义位域的时候使用的是uchr类型,所以,“而后面一个是对char字节作测试”。


而我这个例子就有些不同了,定义位域的时候使用的仍然是8位的uchr,运算的时候中间结果却是0xFFFFFFFE,而不是0xFE。


当然了,刘前辈不要生气,我没有要和您较劲的意思——小辈不敢,而且俺也确实知道,这种现象应该根本就不叫类型提升,产生这种现象的根本原因在于ARM7指令集的所有运算都是32bit执行的——上面的现象证实了这一点,如果我错了,请各位前辈教导。


所以,大家的误会其实是:一方**说“这种现象根本不是类型提升”,C语言有自己的规范,不能胡乱发明概念或扩展C语言概念的应用范围。而另一方则说,这种现象和类型提升十分相似,没有必要咬文嚼字。


所以,双方其实都是对的,只是看问题的角度不同而已,一方是从C语言和C语言标准的角度来看待这个问题的,另一方则是从C语言的实现和汇编甚至CPU指令的角度来看待这个问题的。


小人乱放一同,大侠们如果觉得这“屁”很臭,就大骂一通走人就成了:lol

QQ截图未命名3.png (9.12 KB )

QQ截图未命名3.png

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则