[电路设计] C++还是C欢迎灌水拍砖 (灌水榜20名 一人一份)

[复制链接]
5002|27
john_lee 发表于 2011-12-16 12:58 | 显示全部楼层
楼上说的确实是实情。但也不是说没有师傅就学不好c++,只不过相对来说难度大些,时间长些。
 楼主| kyzb001 发表于 2011-12-16 13:43 | 显示全部楼层
手头上 有二本书~
一本是C++ primer
一本是C和指针.
:D
乡村男孩 发表于 2011-12-16 13:47 | 显示全部楼层
到目前为止没用用过C++,所以还不能真正知道面向对象和面向过程的真正区别,但是C++的一些机制还是很不错,用C实现的东西到后面来发现如果会C++,那样写出来更加能让程序结构紧凑和完整;
 楼主| kyzb001 发表于 2011-12-16 16:20 | 显示全部楼层
我是c++高手...

如果没有师傅带,用c++写和c没什么优势,因为你不知道如何写才有优势
icecut 发表于 2011-12-16 12:53
这师傅上哪里找去哇!!!
john_lee 发表于 2011-12-17 01:50 | 显示全部楼层
本帖最后由 john_lee 于 2011-12-17 02:00 编辑

嗯,不错,各有各的观点,欢迎讨论。

在大程序中,使用C++是有优势的,这一点貌似大家都认同。

那我们就往程序的细节方向讨论,看看C++是否还有优势。

在单片机中,特殊功能寄存器(SFR, Special Function Register)的访问可谓是非常细节了,我们知道,RISC架构的CPU,程序要修改一个SFR中的某一个或某几个特殊功能位域(SFBF, Special Function Bit Field)时,需要将整个SFR读到CPU寄存器中,在CPU寄存器中修改完毕后,再写回到SFR,这就是所谓的“读-修改-写”过程。

那么,使用C语言应该如何来描述这个操作?
一般有两种方法:
1、位操作(与,或,反,异或)
例如:对SFR中的bit2, bit5置1,一般的写法大致如下:
  1. #define SFB_LED 0x04 // 或(1 << 2)
  2. #define SFB_RELAY 0x20 // 或(1 << 5)
  3. SFR |= SFB_LED | SFB_RELAY;
可以看出,位操作是以整个SFR为目标的赋值操作,表达式右值就是SFR,编译器生成的代码会先“读”,然后“修改”所有需要修改的位,最后“写”,所以代码效率是最高的,这是位操作的优点。但是,SFB_LED, SFB_RELAY等宏代表的SFBF,与SFR在语法逻辑上没有任何关系,编译器不可能知道这些SFB_LED, SFB_RELAY是属于这个SFR的,如果你错写成了另外的宏(数值定义),编译照样通过。这个属于安全性问题。至于算不算缺点,那就要看有没有其它方法,使编译器可以检查SFR和SFBF的关系。如果没有,那么位操作就是目前最好的方法了;否则,安全性差就是位操作的缺点。

幸运的是,有方法,那就是位域。

2、位域
我们还是以上面的例子,但是用位域的方式实现:
  1. struct sfr {
  2.     uint32_t : 2;
  3.     volatile uint32_t SFB_LED : 1;
  4.     uint32_t : 2;
  5.     volatile uint32_t SFB_RELAY : 1;
  6. };
  7. extern struct sfr SFR;
  8. SFR.SFB_LED = 1;
  9. SFR.SFB_RELAY = 1;
使用位域的方式来定义SFBF,利用了语言本身的作用域的约束检查,编译器可以明确地知道SFB_LED,SFB_RELAY是属于SFR的,当你写错时,编译器一定不会任你错下去,这正好克服了位操作安全性差的缺点。

但是,我们还注意到了,位域的操作,不再是以整个SFR为目标了,而是以其中的某个位域为目标,而位域的定义,由于是SFBF,为了保证操作的确定性以及防止优化,所以,一般需要加上volatile修饰,这样的结果是,程序每修改一个SFBF,编译器就会生成一个“读-修改-写”的过程。

如果我们的程序修改了同一个SFR中的两个SFBF,按刚才的规则,编译器将会生成两个“读-修改-写”,但我们可能不需要这两个SFBF有一定的先后顺序(甚至需要两个SFBF同时操作),而希望编译器把两个“读-修改-写”合并为一个。但是我们失望了。

现在,我们来做个小结:
SFBF操作方式: 位操作 位域
效率:
安全性:








看来,鱼和熊掌,不可兼得啊。

接下来,试试C++。

我们定义了一堆类,模板,重载操作符等等(实现细节就省了,否则两屏幕都写不完)。

展示一下用法:
  1.                                  // 等效的C表达式为:
  2. SFR().SFB_LED(1).SFB_RELAY(1);   // SFR |= SFB_LED | SFB_RELAY;
  3. SFR().SFB_LED(0).SFB_RELAY(0);   // SFR &= ~(SFB_LED | SFB_RELAY);
  4. SFR().SFB_RELAY(0).SFB_LED(1);   // SFR = (SFR | SFB_LED) & ~SFB_RELAY;
  5. SFR(0).SFB_LED(1);               // SFR = SFB_LED;
  6. SFR(~0).SFB_LED(0);              // SFR = ~SFB_LED;
  7. SFR(0);                          // SFR = 0;
如果嫌可读性不好,那么可以这样:
  1. SFR()
  2.     .SFB_LED(1)
  3.     .SFB_RELAY(1);
C++的SFR访问方法,不仅安全性同位域一样有保证,效率也同位操作一样高效,并且写法也很优雅。

总结了:
SFBF操作方式: C位操作 C位域 C++
效率:
安全性:
 楼主| kyzb001 发表于 2011-12-17 10:08 | 显示全部楼层
:victory:  犀利!
weshiluwei6 发表于 2011-12-18 14:01 | 显示全部楼层
菜鸟飞啊非啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部