C語言 雜記

2021-08-16 01:35:18 字數 4075 閱讀 9294

1、常量溢位

u16  adc_temp = 0;   //應為: u32  adc_temp = 0;

for(i=0;i<100;i++)

adc_temp /= 100;

1.2、資料範圍溢位

將乙個數拆分為n個隨機數

for(i=0;i<200;i++)

break;

}}

可更正為:

for(i=0;i<200;i++)

else //小於或等於0xff直接記錄並退出

}

2、標頭檔案中巨集定義與宣告

#ifndef __bsp_11_h

#define __bsp_11_h

#include "stm32f10x.h"

#define data_codeline 140

//u8 data_codeline = 140; //巨集定義data_codeline 為140是可以的,但是當

//宣告為u8型別的變數時,會報"多重定義"的錯誤

#endif

原因是當此標頭檔案被不同c檔案「include」時,兩個c檔案都分別宣告data_codeline,導致多重定義。

採用巨集定義可以避免此問題。

3、資料的進製

stmflash_write(0x8019000,flashbuff,10);

stmflash_write(0x8019050,flashbuff,10);

for(i=0;i<2;i++)

stmflash_read(0x8019000+i*50,flashbuff,10); //應為i*0x50

原本第二次想讀取0x8019050開始,連續10個半字大小的位址的資料。但是「i*50『這裡錯誤,應為」i*0x50「。否則將導致從0x8019032這個位址開始讀取。

4、避免使用null指標

舉個例子,編譯環境為visual studio 2015:

int main() 

咋一看沒問題,其實會報錯:

這是因為,宣告的指標「p1」,沒有指向任一記憶體位址。在編譯器裡它預設指向「null」,所以從邏輯上來說,對「p1」指向的記憶體位址取值,這本身不可取。但如果是mdk編譯,是不會報錯的,可見vs的編譯器還是比較強大的。

延伸一下,鍊錶的建立問題。

鍊錶的建立,一般是先宣告鍊錶結構體的指標變數,再通過「malloc(

); 」申請鍊錶結構體大小的記憶體空間,並將空間起始位址賦值給這個指標變數。然後便能通過指標變數,操作它指向的記憶體空間的資料。這裡通過「malloc(

); 」申請記憶體賦值給指標變數的過程,就相當於給指標指定乙個記憶體位址,這樣它就不會是乙個指向「null」的空指標了。

除了使用「malloc(

#include #include //建立鍊錶結構體

typedef struct node

node;

//宣告鍊錶結構體變數以及指標變數

node head, node1, node2 ,tail, *p4;

int main()

編譯執行結果為:

宣告鍊錶結構體變數的時候,變數的位址已經由系統分配完畢。

p4 = &head;
當鍊表結構體指標變數指向頭結點時,我們便能通過操作指標變數來操作頭結點。

p4 = p4->next;
當它改為指向指標域時,因為頭結點指標域指向node1,所以此時它指向node1。

由「malloc(); 」申請記憶體建立的鍊錶儲存在動態儲存區,使用靈活可刪除。

而這種方法建立的鍊錶儲存在靜態儲存區,無法刪除鍊錶釋放ram。

5、char型別表示負數

在mdk下執行以下**:

int main(void)

進入**,檢視變數的值:

然後將「a1」的型別「char」改為「short」,問題解決。

後面找到問題了,是mdk編譯器將「char」型別預設為「unsigned char」型別,可在mdk中修改:

6、指標作為陣列的應用

uint8_t *pbuf;

pbuf[0] = nrf24l01_rw(*pbuf++);

pbuf[1] = nrf24l01_rw(*pbuf++);

pbuf[2] = nrf24l01_rw(*pbuf++);

pbuf[3] = nrf24l01_rw(*pbuf++);

pbuf[4] = nrf24l01_rw(*pbuf++);

原意是想,每傳送乙個資料,將傳送緩衝陣列中對應元素改為接收返回值。

但這裡將指標當作陣列使用出了問題。

分析  「pbuf[0] = nrf24l01_rw(*pbuf++);」

執行  1、「nrf24l01_rw(*pbuf);」

2、「pbuf++;」

3、 「pbuf[0]」等於 「nrf24l01_rw(*pbuf);」執行完畢的返回值

這裡的問題是,「pbuf[0]」的位址是」pbuf「嗎?

並不是的,因為第二步中,執行了「pbuf++;」,所以「pbuf[0]」的位址是」pbuf+1「

也就是說「pbuf[0]」變成了」「pbuf[1]「

7、"i++" 與 "++i" 的問題

int main() , *p1 = arr,y;

y = *p1++ + (*(p1+++1)<<1);

printf("%d\r\n",y);

y = *p1;

printf("%d\r\n", y);

getchar();

}

以上程式輸出結果:

第乙個等式,「*(p1+++1)」,"++"優先順序大於"+",先計算「(*p1+1)」,整個等式計算完畢後,p1再自增

由於第乙個等式「p1」自增2次,所以第二個等式結果為5。

所以第乙個等式等價於:y = arr[0] + (arr[1]<<1);

6、lkt4106加密晶元的坑

乙個小小的加密晶元也能遇到很多坑。。。在這裡慢慢填上

(1)

u8  aa = 0x01, bb = 0xf4;

u16 sum = 0;

sum = ((aa<<8)|bb)/10;

while(1)

上述**「sum」結果應該是「0x01f4」,但是lkt4106執行出來變成了0xf4。解決辦法是分開一步步執行,不要寫在一起。。。

(2)

unsigned char aa = 0x11, bb = 0x22;

unsigned long sum = 0;

sum = aa;

sum |= bb<<8;

while(1)

理論上sum的值為「0x00002211」,實際上變成了「0xffff2211」.解決辦法:

sum  = aa;

sum |= (bb<<8)&0x0000ffff;

C語言 雜記

2n 要表示為 2 n printf d a 引號必須是雙引號,不能是單引號,否則報 error c2664 printf cannot convert parameter 1 from const int to const char conversion from integral type to...

C語言雜記

p是列印位址 指標位址 的,是十六進製制的形式,但是會全部打完,即有多少位列印多少位。32位編譯器的指標變數為4個位元組 32位 64位編譯器的指標變數為8個位元組 64位 在32位編譯器下,使用 p列印指標變數,則會顯示32位的位址 16進製制的 在64位編譯器下,使用 p列印指標變數,則會顯示6...

C語言指標雜記

1.指標就是位址,位址就是指標 2.指標變數 定義某個變數,這個變數中存的是位址 指標 的值 3.void型別的指標在傳參過程中可以接受任何型別指標的值,也可以把自己的值傳給任何型別的指標 4.int p 3 指標p指向int型別的資料,該資料有3個int型別那麼大 5.int arr 2 3 6....