C语言编程方法技巧,C语言编程技巧

C语言编程技巧

volatile的用法

volatile的本意是“易变的” EETOP专业博客---电子工程师自己的家园!~XP0Z,|Rz[#p‑~M7p e6W{5d#k'^0由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:EETOP专业博客---电子工程师自己的家园9x+Q%ww_

static int i=0;jt

[1]

Y/W V5y1t0EETOP专业博客---电子工程师自己的家园$`7@(jC/w7G0hfint main(void)EETOP专业博客---电子工程师自己的家园'C,yk

@4x U­M+]{ ,Q,](b4J!? z p@0...

!xN"N~h

[1]

d;[0while (1)

‑W­MG3S&^P-U7w&C0{EETOP专业博客---电子工程师自己的家园f/\h Zd*Eif (i) dosomething();

6mCWh I

~0}

1f&]I)t5Z0x&q^

[1]

c)T0}

EETOP

专业博客

---

电子工程师自己的家园

0N-O$P'r2r8Pq/O8t

iu^ `i f [0/* Interrupt service routine. */EETOP

专业博客

---

电子工程师自己的家园

T}+i6MY

void ISR_2(void)

$v%^#{*IM4k­u i0{EETOP

专业博客

---

电子工程师自己的家园

C:j(u\ b:`

i=1;EETOP

专业博客

---

电子工程师自己的家园

6A!G#w­?C-? }&kO

}cQM(ED"A0

#x3ix"?@)J‑Tk E I0

程序的本意是希望

ISR_2

中断产生时

,

main

当中调用

dosomething

函数

,

但是

,

由于编译器判断在

main

函数里面没有修改过

i,

因此可能只执行一次对从

i

到某寄存器的读操作

,

然后每次

if

判断都只使用这个寄存器里面的

“i

副本

”,

导致

dosomething

永远也不会被调用。如果将将变量加上

volatile

修饰

,

则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中

i

也应该如此说明。

+Z{­e[,{/IzB0EETOP

专业博客

---

电子工程师自己的家园

ADw

VWf;[w&s8R

一般说来

,volatile

用在如下的几个地方:

y­\&V.atr,?-\*V0EETOP

专业博客

---

电子工程师自己的家园

(A-RcO&uY

1

、中断服务程序中修改的供其它程序检测的变量需要加

volatile;EETOP

专业博客

---

电子工程师自己的家园

n?b'w'Aw‑A"u

b3HT:lj,v(K02

、多任务环境下各任务间共享的标志应该加

volatile;*c S.M'Y(r0EETOP

专业博客

---

电子工程师自己的家园

;t5g)AW'Ko­}

?9m1Ha

3

、存储器映射的硬件寄存器通常也要加

volatile

说明

,

因为每次对它的读写都可能由不同意义

;EETOP

专业博客

---

电子工程师自己的家园

E*v |8j2v$b

7_6\#Y;~%p%j­V

[1]

]:Upf0

另外

,

以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写)

,

1

中可以通过关中断来实现

,2

中可以禁止任务调度

,3

中则只能依靠硬件的良好设计了。

关于C++中的内联函数(inline)

在c++中,为了解决一些频繁调用的小函数大量消耗栈空间或者是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数。]&CMg

[1]

R6s%MU08O I'D+eC&N3{‑X6c*k0可能说到这里,很多人还不明白什么是栈空间,其实栈空间就是指放置程序的局部数据也就是函数内数据的内存空间,在系统下,栈空间是有限的,如果频繁大量的使用就会造成因栈空间不足所造成的程序出错的问题,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。

下面我们来看一个例子:

#include 

cR Y+Y']1ba&h+Hh3L0#include 

VHN&Z+J*u5e0usingnamespacestd;

OS7a2RD{(~ J5}'M*{

6A \(Z$B6B0inlinestringdbtest(inta);//函数原形声明为inline即:内联函数%E

[1]

_'S{#Bq0K4c6lx k3N0  EETOP专业博客---电子工程师自己的家园8U A@

dg/M9U3J8p eM7Z

EETOP

专业博客

---

电子工程师自己的家园

+o%H)E?-I+V1a*]x

void

main

()

:r Y Q&Oz*^Fs|'HN0{

5M [|UXx

[1]

j|o0

for

(

int

i=1;i<=10;i++)

,p y3sc‑pHK)`&C0    {  EETOP

专业博客

---

电子工程师自己的家园

-I6J

I:S5E2_ G.C K8^ l

cout

<

Bk"a‑Z/cr9Q0    }  EETOP

专业博客

---

电子工程师自己的家园

C6~ SN6?$]l

cin

.get();  EETOP

专业博客

---

电子工程师自己的家园

[1]

O}h E2v7p"g

m`X!k,o$PlI0}  EETOP

专业博客

---

电子工程师自己的家园

t!s.o-if#X.|EETOP

专业博客

---

电子工程师自己的家园

­p;X;yHu

string

dbtest(

int

a)

//

这里不用再次

inline,

当然加上

inline

也是不会出错的

EETOP

专业博客

---

电子工程师自己的家园

5D(TGk(u:Bw)F8w&i

{

7L2b-w‑sXZ!yJ

[,P j0

return

(a%2>0)?"

":"

";  EETOP

专业博客

---

电子工程师自己的家园

~,i"V:k-EQ

EETOP

专业博客

---

电子工程师自己的家园

Motp#vO"q)F

}

上面的例子就是标准的内联函数的用法,使用inline修饰带来的好处我们表面看不出来,其实在内部的工作就是在每个for循环的内部所有调用dbtest(i)的地方都换成了(i%2>0)?"奇":"偶"这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。

说到这里很多人可能会问,既然inline这么好,还不如把所谓的函数都声明成inline,嗯,这个问题是要注意的,inline的使用是有所限制的,inline只适合函数体内代码简单的函数使用,不能包含复杂的结构控制语句例如while switch,并且不能内联函数本身不能是直接递归函数(自己内部还调用自己的函数)。

说到这里我们不得不说一下在c语言中广泛被使用的#define语句,是的define的确也可以做到inline的这些工作,但是define是会产生副作用的,尤其是不同类型参数所导致的错误,由此可见inline有更强的约束性和能够让编译器检查出更多错误的特性,在c++中是不推荐使用define的。参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值