精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

你不得不知道的嵌入式C的高級用法

Q4MP_gh_c472c21 ? 來源:未知 ? 作者:胡薇 ? 2018-07-02 14:33 ? 次閱讀

1內存管理

我們需要知道——變量,其實是內存地址的一個抽像名字罷了。在靜態編譯的程序中,所有的變量名都會在編譯時被轉成內存地址。機器是不知道我們取的名字的,只知道地址。

內存的使用時程序設計中需要考慮的重要因素之一,這不僅由于系統內存是有限的(尤其在嵌入式系統中),而且內存分配也會直接影響到程序的效率。因此,我們要對C語言中的內存管理,有個系統的了解。

在C語言中,定義了4個內存區間:代碼區;全局變量和靜態變量區;局部變量區即棧區;動態存儲區,即堆區;具體如下:

1>棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。

2>堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表。

3>全局區(靜態區)(static)—全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的 另一塊區域。 - 程序結束后由系統釋放。

4>常量區 —常量字符串就是放在這里的。 程序結束后由系統釋放。

5>程序代碼區—存放函數體的二進制代碼。我們來看張圖:

圖1

首先我們要知道,源代碼編譯成程序,程序是放在硬盤上的,而非內存里!只有執行時才會被調用到內存中!我們來看看程序結構,ELF是是Linux的主要可執行文件格式。ELF文件由4部分組成,分別是ELF頭(ELF header)、程序頭表(Program header table)、節(Section)和節頭表(Section header table)。具體如下:

1>Program header描述的是一個段在文件中的位置、大小以及它被放進內存后所在的位置和大小。即要加載的信息

2>Sections保存著object 文件的信息,從連接角度看:包括指令,數據,符號表,重定位信息等等。在圖中,我們可以看到Sections中包括:

text 文本結 存放指令;

rodata 數據結 readonly;

data 數據結 可讀可寫;

3>Section頭表(section header table)包含了描述文件sections的信息。每個section在這個表中有一個入口;每個入口給出了該section的名字,大小,等等信息。相當于 索引!

而程序被加載到內存里面,又是如何分布的呢?我們看看上圖中:

1正文和初始化的數據和未初始化的數據就是我們所說的數據段,正文即代碼段;

2>正文段上面是常量區,常量區上面是全局變量和靜態變量區,二者占據的就是初始化的數據和未初始化的數據那部分;

3>再上面就是堆,動態存儲區,這里是上增長;

4>堆上面是棧,存放的是局部變量,就是局部變量所在代碼塊執行完畢后,這塊內存會被釋放,這里棧區是下增長;

5>命令行參數就是001之類的,環境變量什么的前面的文章已經講過,有興趣的可以去看看。

我們知道,內存分為動態內存和靜態內存,我們先講靜態內存。

1.1靜態內存

存儲模型決定了一個變量的內存分配方式和訪問特性,在C語言中主要有三個維度來決定:存儲時期 、作用域 、鏈接。

1、存儲時期存儲時期:變量在內存中的保留時間(生命周期)存儲時期分為兩種情況,關鍵是看變量在程序執行過程中會不會被系統自動回收掉。

1) 靜態存儲時期 Static在程序執行過程中一旦分配就不會被自動回收。通常來說,任何不在函數級別代碼塊內定義的變量。無論是否在代碼塊內,只要采用static關鍵字修飾的變量。

2) 自動存儲時期 Automatic除了靜態存儲以外的變量都是自動存儲時期的,或者說只要是在代碼塊內定義的非static的變量,系統會肚臍自動非配和釋放內存;

2、作用域作用域:一個變量在定義該變量的自身文件中的可見性(訪問或者引用)在C語言中,一共有3中作用域:1) 代碼塊作用域在代碼塊中定義的變量都具有該代碼的作用域。從這個變量定義地方開始,到這個代碼塊結束,該變量是可見的;

2) 函數原型作用域出現在函數原型中的變量,都具有函數原型作用域,函數原型作用域從變量定義處一直到原型聲明的末尾。

3) 文件作用域一個在所有函數之外定義的變量具有文件作用域,具有文件作用域的變量從它的定義處到包含該定義的文件結尾處都是可見的;

3、鏈接鏈接:一個變量在組成程序的所有文件中的可見性(訪問或者引用);C語言中一共有三種不同的鏈接:1) 外部鏈接如果一個變量在組成一個程序的所有文件中的任何位置都可以被訪問,則稱該變量支持外部鏈接;

2) 內部鏈接如果一個變量只可以在定義其自身的文件中的任何位置被訪問,則稱該變量支持內部鏈接。

3) 空鏈接如果一個變量只是被定義其自身的當前代碼塊所私有,不能被程序的其他部分所訪問,則成該變量支持空鏈接

我們來看一個代碼示例:

#include

inta = 0;// 全局初始化區

char*p1; //全局未初始化區

intmain()

{

intb; //b在棧區

chars[] = "abc"; //棧

char*p2; //p2在棧區

char*p3 = "123456"; //123456\0在常量區,p3在棧上。

staticintc =0; //全局(靜態)初始化區

p1 = (char*)malloc(10);

p2 = (char*)malloc(20); //分配得來得10和20字節的區域就在堆區。

strcpy(p1, "123456"); //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。

}

·

1.2動態內存

當程序運行到需要一個動態分配的變量時,必須向系統申請取得堆中的一塊所需大小的存儲空間,用于存儲該變量。當不在使用該變量時,也就是它的生命結束時,要顯示釋放它所占用的存儲空間,這樣系統就能對該空間 進行再次分配,做到重復使用有線的資源。下面介紹動態內存申請和釋放的函數。

1.2.1 malloc 函數

malloc函數原型:

size是需要動態申請的內存的字節數。若申請成功,函數返回申請到的內存的起始地址,若申請失敗,返回NULL。我們看下面這個例子:

使用該函數時,有下面幾點要注意:1)只關心申請內存的大??;2)申請的是一塊連續的內存。記得一定要寫出錯判斷;3)顯示初始化。即我們不知這塊內存中有什么東西,要對其清零;

1.2.2 free函數

在堆上分配的額內存,需要用free函數顯示釋放,函數原型如下:

使用free(),也有下面幾點要注意:1)必須提供內存的起始地址;調用該函數時,必須提供內存的起始地址,不能夠提供部分地址,釋放內存中的一部分是不允許的。

2)malloc和free配對使用;編譯器不負責動態內存的釋放,需要程序員顯示釋放。因此,malloc與free是配對使用的,避免內存泄漏。

p = NULL是必須的,因為雖然這塊內存被釋放了,但是p仍指向這塊內存,避免下次對p的誤操作;

3)不允許重復釋放因為這塊內存被釋放后,可能已另分配,這塊區域被別人占用,如果再次釋放,會造成數據丟失;

1.2.3 其它相關函數

calloc函數分配內存需要考慮存儲位置的類型。realloc函數可以調整一段動態分配內存的大小

1.3堆和棧比較

1)申請方式

stack: 由系統自動分配。 例如,聲明在函數中一個局部變量 int b; 系統自動在棧中為b開辟空間heap: 需要程序員自己申請,并指明大小,在c中malloc函數 ,如p1 = (char *)malloc(10);

2)申請后系統的響應棧:只要棧的剩余空間大于所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。

堆:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大于所申請空間的堆結點,然后將該結點從空閑結點鏈表中刪除,并將該結點的空間分配給程序,另外,對于大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,由于找到的堆結點的大小不一定正好等于申請的大小,系統會自動的將多余的那部分重新放入空閑鏈表中。

3)申請大小的限制棧:棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由于系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

4)申請效率的比較棧由系統自動分配,速度較快。但程序員是無法控制的。堆是由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便。

5)堆和棧中的存儲內容棧:在函數調用時,第一個進棧的是主函數中后的下一條指令(函數調用語句的下一條可執行語句)的地址,然后是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然后是函數中的局部變量。注意靜態變量是不入棧的。 當本次函數調用結束后,局部變量先出棧,然后是參數,最后棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。

堆:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容由程序員安排。

6)存取效率的比較

chars1[] = "aaaaaaaaaaaaaaa";

char*s2 = "bbbbbbbbbbbbbbbbb";

aaaaaaaaaaa是在運行時刻賦值的;而bbbbbbbbbbb是在編譯時就確定的;但是,在以后的存取中,在棧上的數組比指針所指向的字符串(例如堆)快。比如:

對應的匯編代碼

第一種在讀取時直接就把字符串中的元素讀到寄存器cl中,而第二種則要先把指針值讀到edx中,再根據edx讀取字符,顯然慢了。

7)最后總結堆和棧的區別可以用如下的比喻來看出:

棧就像我們去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。

堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。

2內存對齊

2.1 #pragma pack(n) 對齊用法詳解

1.什么是對齊,以及為什么要對齊現代計算機中內存空間都是按照byte劃分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定變量的時候經常在特定的內存地址訪問,這就需要各類型數據按照一定的規則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。

對齊的作用和原因:各個硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類型的數據只能從某些特定地址開始存取。其他平臺可能沒有這種情況, 但是最常見的是如果不按照適合其平臺要求對數據存放進行對齊,會在存取效率上帶來損失。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設為 32位系統)如果存放在偶地址開始的地方,那么一個讀周期就可以讀出,而如果存放在奇地址開始的地方,就可能會需要2個讀周期,并對兩次讀出的結果的高低字節進行拼湊才能得到該int數據。顯然在讀取效率上下降很多。這也是空間和時間的博弈。

2.對齊的實現通常,我們寫程序的時候,不需要考慮對齊問題。編譯器會替我們選擇時候目標平臺的對齊策略。當然,我們也可以通知給編譯器傳遞預編譯指令而改變對指定數據的對齊方法。 但是,正因為我們一般不需要關心這個問題,所以因為編輯器對數據存放做了對齊,而我們不了解的話,常常會對一些問題感到迷惑。最常見的就是struct數據結構的sizeof結果,出乎意料。為此,我們需要對對齊算法所了解。

作用:指定結構體、聯合以及類成員的packing alignment;語法:

#pragma pack( [show] | [push | pop] [, identifier], n )

說明:1>pack提供數據聲明級別的控制,對定義不起作用;2>調用pack時不指定參數,n將被設成默認值;3>一旦改變數據類型的alignment,直接效果就是占用memory的減少,但是performance會下降;

3.語法具體分析1>show:可選參數;顯示當前packing aligment的字節數,以warning message的形式被顯示;

2>push:可選參數;將當前指定的packing alignment數值進行壓棧操作,這里的棧是the internal compiler stack,同時設置當前的packing alignment為n;如果n沒有指定,則將當前的packing alignment數值壓棧;

3>pop:可選參數;從internal compiler stack中刪除最頂端的record;如果沒有指定n,則當前棧頂record即為新的packing alignment數值;如果指定了n,則n將成為新的packing aligment數值;如果指定了identifier,則internal compiler stack中的record都將被pop直到identifier被找到,然后pop出identitier,同時設置packing alignment數值為當前棧頂的record;如果指定的identifier并不存在于internal compiler stack,則pop操作被忽略;

4>identifier:可選參數;當同push一起使用時,賦予當前被壓入棧中的record一個名稱;當同pop一起使用時,從internal compiler stack中pop出所有的record直到identifier被pop出,如果identifier沒有被找到,則忽略pop操作;5>n:可選參數;指定packing的數值,以字節為單位;缺省數值是8,合法的數值分別是1、2、4、8、16。

4.重要規則

1>復雜類型中各個成員按照它們被聲明的順序在內存中順序存儲,第一個成員的地址和整個類型的地址相同;

2>每個成員分別對齊,即每個成員按自己的方式對齊,并最小化長度;規則就是每個成員按其類型的對齊參數(通常是這個類型的大小)和指定對齊參數中較小的一個對齊;

3>結構、聯合或者類的數據成員,第一個放在偏移為0的地方;以后每個數據成員的對齊,按照#pragma pack指定的數值和這個數據成員自身長度兩個中比較小的那個進行;也就是說,當#pragma pack指定的值等于或者超過所有數據成員長度的時候,這個指定值的大小將不產生任何效果;

4>復雜類型(如結構)整體的對齊<注意是“整體”>是按照結構體中長度最大的數據成員和#pragma pack指定值之間較小的那個值進行;這樣在成員是復雜類型時,可以最小化長度;

5>結構整體長度的計算必須取所用過的所有對齊參數的整數倍,不夠補空字節;也就是取所用過的所有對齊參數中最大的那個值的整數倍,因為對齊參數都是2的n次方;這樣在處理數組時可以保證每一項都邊界對齊;

5.對齊的算法由于各個平臺和編譯器的不同,現以本人使用的gcc version 3.2.2編譯器(32位x86平臺)為例子,來討論編譯器對struct數據結構中的各成員如何進行對齊的。

在相同的對齊方式下,結構體內部數據定義的順序不同,結構體整體占據內存空間也不同,如下:

設結構體如下定義:

結構體A中包含了4字節長度的int一個,1字節長度的char一個和2字節長度的short型數據一個。所以A用到的空間應該是7字節。但是因為編譯器要對數據成員在空間上進行對齊。所以使用sizeof(strcut A)值為8?,F在把該結構體調整成員變量的順序。

這時候同樣是總共7個字節的變量,但是sizeof(struct B)的值卻是12。下面我們使用預編譯指令#progma pack (value)來告訴編譯器,使用我們指定的對齊值來取代缺省的。

sizeof(struct C)值是8。修改對齊值為1:

sizeof(struct D)值為7。

對于char型數據,其自身對齊值為1,對于short型為2,對于int,float,double類型,其自身對齊值為4,單位字節。

6.四個概念值1>數據類型自身的對齊值:就是上面交代的基本數據類型的自身對齊值。

2>指定對齊值:#progma pack (value)時的指定對齊值value。

3>結構體或者類的自身對齊值:其數據成員中自身對齊值最大的那個值。

4>數據成員、結構體和類的有效對齊值:自身對齊值和指定對齊值中小的那個值。 有了這些值,我們就可以很方便的來討論具體數據結構的成員和其自身的對齊方式。有效對齊值N是最終用來決定數據存放地址方式的值,最重要。有效對齊N,就是表示“對齊在N上”,也就是說該數據的”存放起始地址%N=0”. 而數據結構中的數據變量都是按定義的先后順序來排放的。第一個數據變量的起始地址就是數據結構的起始地址。結構體的成員變量要對齊排放,結構體本身也要根 據自身的有效對齊值圓整(就是結構體成員變量占用總長度需要是對結構體有效對齊值的整數倍,結合下面例子理解)。這樣就不能理解上面的幾個例子的值了。

例子分析:分析例子B;

假設B從地址空間0x0000開始排放。該例子中沒有定義指定對齊值,在筆者環境下,該值默認為4。

第一個成員變量b的自身對齊值是1,比指定或者默認指定對齊值4小,所以其有效對齊值為1,所以其存放地址0x0000符合0x0000%1=0.

第二個成員變量a,其自身對齊值為4,所以有效對齊值也為4,所以只能存放在起始地址為0x0004到0x0007這四個連續的字節空間中,符合0x0004%4=0, 且緊靠第一個變量。

第三個變量c,自身對齊值為2,所以有效對齊值也是2,可以存放在0x0008到0x0009這兩個字節空間中,符合0x0008%2=0。所以從0x0000到0x0009存放的都是B內容。再看數據結構B的自身對齊值為其變量中最大對齊值(這里是b)所以就是4,所以結構體的有效對齊值也是4。根據結構體圓整的要求,0x0009到0x0000=10字節,(10+2)%4=0。所以0x0000A到0x000B也為結構體B所占用。故B從0x0000到0x000B共有12個字節,sizeof(struct B)=12;

同理,分析上面例子C:

第一個變量b的自身對齊值為1,指定對齊值為2,所以,其有效對齊值為1,假設C從0x0000開始,那么b存放在0x0000,符合0x0000%1=0;

第二個變量,自身對齊值為4,指定對齊值為2,所以有效對齊值為2,所以順序存放在0x0002、0x0003、0x0004、0x0005四個連續字節中,符合0x0002%2=0。

第三個變量c的自身對齊值為2,所以有效對齊值為2,順序存放在0x0006、0x0007中,符合0x0006%2=0。所以從0x0000到0x00007共八字節存放的是C的變量。

又C的自身對齊值為4,所以C的有效對齊值為2。又8%2=0,C只占用0x0000到0x0007的八個字節。所以sizeof(struct C)=8.

9.2.2字節對齊對程序的影響

先讓我們看幾個例子吧(32bit,x86環境,gcc編譯器):設結構體如下定義:

現在已知32位機器上各種數據類型的長度如下:char:1(有符號無符號同)short:2(有符號無符號同)int:4(有符號無符號同)long:4(有符號無符號同)float:4 double:8那么上面兩個結構大小如何呢?結果是:sizeof(strcut A)值為8sizeof(struct B)的值卻是12

結構體A中包含了4字節長度的int一個,1字節長度的char一個和2字節長度的short型數據一個,B也一樣;按理說A,B大小應該都是7字節。之所以出現上面的結果是因為編譯器要對數據成員在空間上進行對齊。上面是按照編譯器的默認設置進行對齊的結果,那么我們是不是可以改變編譯器的這種默認對齊設置呢,當然可以.例如:

sizeof(struct C)值是8。修改對齊值為1:

sizeof(struct D)值為7。后面我們再講解#pragma pack()的作用.

2.3修改編譯器的默認對齊值

1>在VC IDE中,可以這樣修改:[Project]|[Settings],c/c++選項卡Category的Code Generation選項的Struct Member Alignment中修改,默認是8字節。2>在編碼時,可以這樣動態修改:#pragma pack .注意:是pragma而不是progma.

如果在編程的時候要考慮節約空間的話,那么我們只需要假定結構的首地址是0,然后各個變量按照上面的原則進行排列即可,基本的原則就是把結構中的變量按照 類型大小從小到大聲明,盡量減少中間的填補空間.還有一種就是為了以空間換取時間的效率,我們顯示的進行填補空間進行對齊,比如:有一種使用空間換時間做 法是顯式的插入reserved成員:

reserved成員對我們的程序沒有什么意義,它只是起到填補空間以達到字節對齊的目的,當然即使不加這個成員通常編譯器也會給我們自動填補對齊,我們自己加上它只是起到顯式的提醒作用.

2.4字節對齊可能帶來的隱患

代碼中關于對齊的隱患,很多是隱式的。比如在強制類型轉換的時候。例如:

最后兩句代碼,從奇數邊界去訪問unsignedshort型變量,顯然不符合對齊的規定。

在x86上,類似的操作只會影響效率,但是在MIPS或者sparc上,可能就是一個error,因為它們要求必須字節對齊.

如果出現對齊或者賦值問題首先查看1). 編譯器的big little端設置2). 看這種體系本身是否支持非對齊訪問3). 如果支持看設置了對齊與否,如果沒有則看訪問時需要加某些特殊的修飾來標志其特殊訪問操作。ARM下的對齊處理from DUI0067D_ADS1_2_CompLib type qulifiers有部分摘自ARM編譯器文檔對齊部分對齊的使用:

1.__align(num)這個用于修改最高級別對象的字節邊界。在匯編中使用LDRD或者STRD時就要用到此命令__align(8)進行修飾限制。來保證數據對象是相應對齊。這個修飾對象的命令最大是8個字節限制,可以讓2字節的對象進行4字節對齊,但是不能讓4字節的對象2字節對齊。 __align是存儲類修改,他只修飾最高級類型對象不能用于結構或者函數對象。

2.__packed__packed是進行一字節對齊l 不能對packed的對象進行對齊l 所有對象的讀寫訪問都進行非對齊訪問l float及包含float的結構聯合及未用__packed的對象將不能字節對齊l __packed對局部整形變量無影響

l 強制由unpacked對象向packed對象轉化是未定義,整形指針可以合法定

義為packed。__packed int* p; //__packed int 則沒有意義

2.5對齊或非對齊讀寫訪問帶來問題

__packed structSTRUCT_TEST

{chara;intb;charc;

} ;

//定義如下結構此時b的起始地址一定是不對齊的,在棧中訪問b可能有問題,因為棧上數據肯定是對齊訪問[from CL]

//將下面變量定義成全局靜態不在棧上

staticchar* p;staticstructSTRUCT_TEST a;voidMain()

{

__packed int* q; //此時定義成__packed來修飾當前q指向為非對齊的數據地址下面的訪問則可以

p = (char*)&a;

q = (int*)(p+1);

*q = 0x87654321; /*

得到賦值的匯編指令很清楚

ldr r5,0x20001590 ; = #0x12345678

[0xe1a00005] mov r0,r5

[0xeb0000b0] bl __rt_uwrite4 //在此處調用一個寫4byte的操作函數

[0xe5c10000] strb r0,[r1,#0] //函數進行4次strb操作然后返回保證了數據正確的訪問

[0xe1a02420] mov r2,r0,lsr #8

[0xe5c12001] strb r2,[r1,#1]

[0xe1a02820] mov r2,r0,lsr #16

[0xe5c12002] strb r2,[r1,#2]

[0xe1a02c20] mov r2,r0,lsr #24

[0xe5c12003] strb r2,[r1,#3]

[0xe1a0f00e] mov pc,r14

*//*

如果q沒有加__packed修飾則匯編出來指令是這樣直接會導致奇地址處訪問失敗

[0xe59f2018] ldr r2,0x20001594 ; = #0x87654321

[0xe5812000] str r2,[r1,#0]

*/

//這樣可以很清楚的看到非對齊訪問是如何產生錯誤的

//以及如何消除非對齊訪問帶來問題

//也可以看到非對齊訪問和對齊訪問的指令差異導致效率問題

}

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5072

    文章

    19026

    瀏覽量

    303516
  • 內存管理
    +關注

    關注

    0

    文章

    168

    瀏覽量

    14128

原文標題:嵌入式C的這些高級用法,你都會了嗎?

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    不得不知道的PID控制算法

    行了嗎?是的,增大pwm多少呢?必須要通過算法,因為PWM和速度是個什么關系,對于整個系統來說,誰也不知道。要一點一點的試,加個1%,不夠,再加1%還是不夠,那么第三次還會加1%嗎?很有可能就加2%了
    發表于 02-10 10:30

    嵌入式系統設計要點,學習嵌入式不得不

    嵌入式系統設計要點包括:嵌入式產品特點,開發流程,外加華清遠見全面的學習嵌入式的方法,嵌入式學習不得不看,趕緊下載學習吧
    發表于 05-23 17:57

    關于FPGA,不得不知道的那些事

    做了兩件事,首先,它使能夠自由地搭建需要的硬件平臺,取代了從前使用ASIC(專用集成電路)時所不得不承擔的長開發時間、高額開發經費以及設計風險,另外一點,相比于其它的硬件構成,它允許
    發表于 09-26 14:44

    關于CPU那些不得不知道

    嵌入式開發之CPU的那些事...
    發表于 03-08 07:57

    在main函數運行之前,不得不知的那些事

    在main函數運行之前,不得不知的那些事在c_int00函數中完成的功能有哪些?
    發表于 04-20 06:03

    設計PCB不得不關注的重點

    設計PCB不得不關注的重點
    發表于 04-21 06:24

    嵌入式系統高級C語言編程(凌明)

    嵌入式系統高級C語言編程,經典的教程。。
    發表于 06-17 16:33 ?0次下載

    嵌入式時代已經來臨,嵌入式學習的方法知道多少呢?

    的能力。但是嵌入式專業不同于其他學科,嵌入式專業是一門綜合性非常強,涉及知識面非常廣的學科,對于初學者來說,面對那么多教程,課本,那么多知識點,往往不知道從何處下手,不知道哪些是重點,
    發表于 07-09 14:25 ?2954次閱讀

    關于可能不知道的printf

    可能不知道的printf
    的頭像 發表于 02-05 12:28 ?2595次閱讀
    關于<b class='flag-5'>你</b>可能<b class='flag-5'>不知道</b>的printf

    學習嵌入式技術的重點分享

    很多人嵌入式學習都有些迷茫,不知道從哪里入手,不知道自己的水平位于哪個層次,不知道從哪方面提升,今天我們就從一個8年工作經驗的嵌入式資深工程
    的頭像 發表于 09-23 11:05 ?2752次閱讀

    嵌入式C語言的高級用法

    的重要因素之一,這不僅由于系統內存是有限的(尤其在嵌入式系統中),而且內存分配也會直接影響到程序的效率。因此,我們要對C語言中的內存管理,有個系統的了解。 在C語言中,定義了4個內存區間:代碼區;全局變量和靜態變
    的頭像 發表于 02-20 14:25 ?1464次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>語言的<b class='flag-5'>高級</b><b class='flag-5'>用法</b>

    要用好高精度單片機,那就不得不知道怎么使用浮點數!資料下載

    電子發燒友網為提供要用好高精度單片機,那就不得不知道怎么使用浮點數!資料下載的電子資料下載,更有其他相關的電路圖、源代碼、課件教程、中文資料、英文資料、參考設計、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發表于 04-16 08:46 ?4次下載
    <b class='flag-5'>你</b>要用好高精度單片機,那就<b class='flag-5'>不得不知道</b>怎么使用浮點數!資料下載

    不知道嵌入式Linux系統下的root密碼,修改新密碼并進入系統

    今天一朋友問不知道root 密碼怎么修改。他這個系統是海思平臺的嵌入式Linux系統。然后嘗試了修改并進入系統。嵌入式Linux中的root 密碼忘記了或者想破解別人系統的密碼登陸進去。如果能
    發表于 11-01 17:59 ?14次下載
    <b class='flag-5'>不知道</b><b class='flag-5'>嵌入式</b>Linux系統下的root密碼,修改新密碼并進入系統

    不得不收藏的PCB的Checklist!

    不得不收藏的PCB的Checklist
    發表于 02-09 10:46 ?37次下載
    <b class='flag-5'>不得不</b>收藏的PCB的Checklist!

    揭秘pcb是什么物質:不知道的“化學戰士”

    揭秘pcb是什么物質:不知道的“化學戰士”
    的頭像 發表于 12-14 10:27 ?982次閱讀