日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 大橙子瘋嵌入式


前言

指針,是C語言中的一個(gè)重要概念及其特點(diǎn),也是掌握C語言比較困難的部分。指針也就是內(nèi)存地址,指針變量是用來存放內(nèi)存地址的變量。

本質(zhì)還是一個(gè)變量,指針提供了一種對(duì)存儲(chǔ)位置的動(dòng)態(tài)訪問手段,(相對(duì)于普通變量而言,普通變量只能訪問自己所占的存儲(chǔ)位置)

內(nèi)存地址對(duì)齊,是計(jì)算機(jī)在內(nèi)存中的數(shù)據(jù)排列、訪問數(shù)據(jù)的方式,包含了基本數(shù)據(jù)對(duì)齊和結(jié)構(gòu)體數(shù)據(jù)對(duì)齊的兩種相互獨(dú)立又相互關(guān)聯(lián)的部分。

現(xiàn)代計(jì)算機(jī)在內(nèi)存中讀寫數(shù)據(jù)是按字節(jié)塊進(jìn)行操作,理論上任意類型的變量訪問可以從任何地址開始,但是計(jì)算機(jī)系統(tǒng)對(duì)任意數(shù)據(jù)類型在內(nèi)存中存放位置有限,它會(huì)要求這些數(shù)據(jù)的首地址的值為K(4位或者8位)的整數(shù)倍。

如何踩坑的?

在一份十分優(yōu)秀的代碼中,指針的使用率占比很高,因?yàn)橹羔樐茏尨a實(shí)現(xiàn)變得更自由、更高效和更方便等諸多優(yōu)點(diǎn),可對(duì)于不十分熟悉指針的朋友來說,用起來也許就是災(zāi)難(常見的就是程序跑飛)

因此,通過指針的使用率大概就能判斷一個(gè)人的編程能力水平

請(qǐng)看下面的代碼,運(yùn)行結(jié)果是怎么樣的呢?

// 假設(shè)數(shù)組首地址為 0x00004000,符合內(nèi)存對(duì)齊:4的倍數(shù) static unsigned char sg_arrBuf[100]; int main() { memset(sg_arrBuf, 0, sizeof(sg_arrBuf)); // 地址為 0x00004000 uint8_t *pucVal = (uint8_t *)&sg_arrBuf[0]; // 地址為 0x00004001 uint16_t *puiVal = (uint16_t *)&sg_arrBuf[1];

 *pucVal = 20; // HEX: 0x14 *puiVal = 2000; // HEX: 0x07d0 printf("HEX: "); for (int i = 0; i < 3; i++)
 { printf("%02x ", sg_arrBuf[i]);
 } printf("\n"); return 0;
}

很多朋友期望的結(jié)果如下(小端模式):

HEX: 14 d0 07 

事實(shí)真的一定如此嗎?

不一定!

也許部分朋友在自己電腦上打開 VS 復(fù)制粘貼運(yùn)行了,編譯后運(yùn)行,結(jié)果還真和上面一樣!??!你這不是在忽悠人嗎!??!

那有試過在 MCU 上跑過嗎?是不是程序跑飛了?

為什么?

當(dāng)計(jì)算機(jī)讀取或?qū)懭雰?nèi)存地址時(shí),它將以字(word)大小的塊進(jìn)行存儲(chǔ)。數(shù)據(jù)對(duì)齊意味著將數(shù)據(jù)放在等于字長(zhǎng)的倍數(shù)的內(nèi)存偏移處,正是由于這種CPU處理內(nèi)存的方式從而提高了系統(tǒng)的性能。大多數(shù)CPU只能訪問內(nèi)存對(duì)齊的地址。

意味著部分系統(tǒng)架構(gòu)體系對(duì)于未對(duì)齊的地址進(jìn)行訪問時(shí)會(huì)發(fā)生異常,如果嘗試去訪問內(nèi)存未對(duì)齊的變量進(jìn)行操作會(huì)導(dǎo)致總線錯(cuò)誤。它只支持對(duì)齊訪問
比如我們?cè)L問一個(gè) 4 字節(jié) (Double Word) 型的變量時(shí),如果這個(gè)變量的起始地址是能被 4 整除的話,我們說這種訪問是雙字節(jié)對(duì)齊的。如果訪問一個(gè) 2 字節(jié) ( Word ) 變量,當(dāng)起始地址能被 2 整除時(shí)是對(duì)齊的。訪問字節(jié) ( Byte ) 型變量,總是對(duì)齊的。

根據(jù)這個(gè)就能很快鎖定問題原因了,那就是程序運(yùn)行到這個(gè)位置就導(dǎo)致總線錯(cuò)誤,從而跑飛了。

// 地址為 0x00004001,未對(duì)齊 *puiVal = 2000; // HEX: 0x07d0 

預(yù)防及解決措施

關(guān)于上述的寫法,有些朋友可能在電腦端實(shí)現(xiàn)了某個(gè)功能,電腦測(cè)試沒有任何問題,但是一旦移植到 MCU 上就不行,那么抓緊檢查一下是不是這個(gè)問題呢。
因此,為了確保我們的代碼有很高的移植性和穩(wěn)定性,那么一定要預(yù)防這種情況,可以通過采用訪問字節(jié) ( Byte ) 型變量,也可以使用memcpy的方式處理這種操作就能避免這種問題。

// 假設(shè)數(shù)組首地址為 0x00004000,符合內(nèi)存對(duì)齊: 4的倍數(shù) static unsigned char sg_arrBuf[100]; int main() { memset(sg_arrBuf, 0, sizeof(sg_arrBuf)); uint8_t ucVal = 20; uint16_t uiVal = 2000; memcpy(&sg_arrBuf[0], &ucVal, 1); memcpy(&sg_arrBuf[1], &uiVal, 2); printf("HEX: "); for (int i = 0; i < 3; i++)
 { printf("%02x ", sg_arrBuf[i]);
 } printf("\n"); return 0;
}

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉