C語言編程技巧
volatile的用法
volatile的本意是“易變的”
由於訪問寄存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化。比如:
static int i=0;
int main(void)
@4x UM+]
{ ...
while (1)
{
if (i) dosomething();
}
}
/* Interrupt service routine. */
void ISR_2(void)
{
i=1;
}
程序的本意是希望ISR_2中斷產生時,在main當中調用dosomething函數,但是,由於編譯器判斷在main函數裏面沒有修改過i,因此可能只執行一次對從i到某寄存器的讀操作,然後每次if判斷都只使用這個寄存器裏面的“i副本”,導致dosomething永遠也不會被調用。如果將將變量加上volatile修飾,則編譯器保證對此變量的讀寫操作都不會被優化(肯定執行)。此例中i也應該如此說明。
一般說來,volatile用在如下的幾個地方:
1、中斷服務程序中修改的供其它程序檢測的變量需要加volatile;
2、多任務環境下各任務間共享的標誌應該加volatile;
3、存儲器映射的硬件寄存器通常也要加volatile說明,因爲每次對它的讀寫都可能由不同意義;
另外,以上這幾種情況經常還要同時考慮數據的完整性(相互關聯的幾個標誌讀了一半被打斷了重寫),在1中可以通過關中斷來實現,2中可以禁止任務調度,3中則只能依靠硬件的良好設計了。
關於C++中的內聯函數(inline)
在c++中,爲了解決一些頻繁調用的小函數大量消耗棧空間或者是叫棧內存的問題,特別的引入了inline修飾符,表示爲內聯函數。
可能說到這裏,很多人還不明白什麼是棧空間,其實棧空間就是指放置程序的局部數據也就是函數內數據的內存空間,在系統下,棧空間是有限的,如果頻繁大量的使用就會造成因棧空間不足所造成的程序出錯的問題,函數的死循環遞歸調用的最終結果就是導致棧內存空間枯竭。
下面我們來看一個例子:
#include <iostream>
#include <string>
using namespace std;
OS7a2RD{(~ J5}'M*{
inline string dbtest(int a); //函數原形聲明爲inline即:內聯函數
void main()
{
for (int i=1;i<=10;i++)
{
cout << i << ":" << dbtest(i) << endl;
}
cin.get();
}
string dbtest(int a)//這裏不用再次inline,當然加上inline也是不會出錯的
{
return (a%2>0)?"奇":"偶";
}
上面的例子就是標準的內聯函數的用法,使用inline修飾帶來的好處我們表面看不出來,其實在內部的工作就是在每個for循環的內部所有調用dbtest(i)的地方都換成了(i%2>0)?"奇":"偶"這樣就避免了頻繁調用函數對棧內存重複開闢所帶來的消耗。
說到這裏很多人可能會問,既然inline這麼好,還不如把所謂的函數都聲明成inline,嗯,這個問題是要注意的,inline的使用是有所限制的,inline只適合函數體內代碼簡單的函數使用,不能包含複雜的結構控制語句例如while switch,並且不能內聯函數本身不能是直接遞歸函數(自己內部還調用自己的函數)。
說到這裏我們不得不說一下在c語言中廣泛被使用的#define語句,是的define的確也可以做到inline的這些工作,但是define是會產生副作用的,尤其是不同類型參數所導致的錯誤,由此可見inline有更強的約束性和能夠讓編譯器檢查出更多錯誤的特性,在c++中是不推薦使用define的。參考http://wenku.it168.com/d_000069212.shtml