1、CPU對數據兩種存儲模式:小端存儲和大端存儲 (Little-Endian and Big-Endian)
如整數0x12345678在內存中應該如下存放:
地低: base | base+1 | base+2 | base+3 |
------------------------------------------------ |
大端 | 12 | 34 | 56 | 78 |
----------------------------------------------- |
小端 | 78 | 56 | 34 | 12 |
程序如下:
...........
union{
char b;
int a;
}endiandata;//聯合體http://www.docin.com/p-4480156.html
endiandata.a=0x12345678;
printf("%x\n",endiandata.b);
if(endiandata.b==0x78)
printf("Little-Endian\n");
else if(endiandata.b==0x12)
printf("Big-Endian\n");
else
printf("Error\n");........................
2、前置雙目運算符++a和後置雙目運算符a++
http://liuyunfeng484.blog.163.com/blog/static/668317152009817739170/
++a { return *this } //先+1再反回
a++ { old = data; ++(*this);return Old} //先返回再+1
當使用前綴用法,即先書寫自增/自減運算符再書寫其操作數時,程序首先對該操作數進行引用,再對其進行加1或減1及賦值;
當使用後綴用法,即先書寫操作數再書寫自增/自減運算符時,程序首先對操作數進行加1或減1及賦值,再對該操作數進行引用;
http://eol.bit.edu.cn/res2006/data/080605/U/100/bjjch/bjjch_02_04_01.htm
測試如下
#include"stdio.h"
int main()
{
int a,b,c,d;
a=10;
b=a++;
c=++a;
d=10*a++;printf("b:%d\tc:%d\td:%d\n",b,c,d);
return 0;
}輸出結果爲
b:10 c:12 d:120
3、const int a(int const a)、const int *a、int * const a和int const * a const;
const int a(int const a) 兩個的作用是一樣,a是一個常整型數。
const int *a 意味着a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。
int * const a 意思a是一個指向整型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。
int const * a const 最後一個意味着a是一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時指針也是不可修改的)。
關鍵字const的意義:
1) 關鍵字const的作用是爲給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數爲常量是爲了告訴了用戶這個參數的應用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學會感謝這點多餘的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。)
2) 通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
3) 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。
4 、關鍵字volatile有什麼含意?並給出三個不同的例子
一個定義爲volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是volatile變量的幾個例子:
1) 並行設備的硬件寄存器(如:狀態寄存器)
2) 一箇中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
3) 多線程應用中被幾個任務共享的變量
volatile的重要性:
1)一個參數既可以是const還可以是volatile嗎?解釋爲什麼。
是的。一個例子是隻讀的狀態寄存器。它是volatile因爲它可能被意想不到地改變。它是const因爲程序不應該試圖去修改它。
2); 一個指針可以是volatile 嗎?解釋爲什麼。
是的。儘管這並不很常見。一個例子是當一箇中服務子程序修該一個指向一個buffer的指針時。
3); 下面的函數有什麼錯誤:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
這段代碼的目的是用來返指針*ptr指向值的平方,但是,由於*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由於*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
5、中斷(Interrupts)
中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提供一種擴展—讓標準C支持中斷。具代表事實是,產生了一個新的關鍵字 __interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一箇中斷服務子程序(ISR),評論一下這段代碼的。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}
這個函數有太多的錯誤了,以至讓人不知從何說起了:
1)ISR 不能返回一個值。如果你不懂這個,那麼你不會被僱用的。
2) ISR 不能傳遞參數。如果你沒有看到這一點,你被僱用的機會等同第一項。
3) 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點運算。此外,ISR應該是短而有效率的,在ISR中做浮點運算是不明智的。
6、關鍵字static的作用
1)在函數體,一個被聲明爲靜態的變量在這一函數被調用過程中維持其值不變。
2) 在模塊內(但在函數體外),一個被聲明爲靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。
3) 在模塊內,一個被聲明爲靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地範圍內使用。
7、uC/OS-II移植的的基本要求
對微處理器的基本要求
1)處理器的C編譯器能產生可重入代碼
2)用C語言就可以實現開關中斷
3)處理器至少能支持定時中斷,中斷頻率一般在10~100HZ之間
4)處理器能夠支持硬件堆棧,容量可達幾KB;
5)處理器有堆棧指針和讀/寫CPU其它寄存器、堆棧內容或內存的指令
對開發工具的要求
1)C編譯器必須支持彙編程序
2)C編譯器必須能支持可重入代碼,因爲uC/OS-II是一個可剝奪內核
3)C編譯器發佈包括彙編器、連接器和定位器。連接器用來將經編譯和彙編後產生的不同的模塊連接成目標文件。定位器用於將代碼和數據放置在目標處理器的指定內存映射空間中,
4)C編譯器必須支持從C中打開和關閉中斷
5)C編譯器必須支持用戶在C語言程序中嵌入彙編語言,這有利於用彙編語言來直接開關中斷
8、C語言中的for和while
http://my.oschina.net/miaoyushun/blog/16093
當while 和for 的循環體內 是空語句時:
i = 10; while(--i); for(i =10 ;i;i--); for(i =10 ;i;--i)
以上三條語句效率相同 對應1條彙編語句 2個機器週期
for(i =0 ;i<10;++i) for(i =0 ;i<10;i++)
以上兩條語句效率相同 對應2條彙編語句 3個機器週期
但while(i--); 效率很低 爲4條語句 6個機器週期
當while 和for 的循環體內 不是空語句時:
for(* ; i ; *) 的效率最高 依然是1條指令 2個機器週期
for(* ; i<10 ; *) 的效率次之 2條指令 3個機器週期
while(i--) 8個機器週期
while(--i) 6個機器週期
while( i++ < * ) 10個機器週期
while( ++ i< * ) 8個機器週期
推薦使用 for(;i;)
另外 如果 循環變量 i 是通過函數參數 形式傳遞的值 for()的效率降低到 6-8個機器週期
總體來說: 如果循環變量是參數 且循環體爲空 while(--i); 是最高效的 其他情況建議 使用 for(*;i ;*){} while(i--)這個被大多數人看好的語句 無論哪種情況下 效率都是最低的;