99精品久久久久久久免费看蜜月/欧美激情做真爱牲交视频/日本不卡不码高清免费观看/三浦惠理子jux240久久 - 他在车里撞了我八次主角是谁

購物車0種商品
IC郵購網(wǎng)-IC電子元件采購商城
如何優(yōu)化C語言代碼
(2011/10/9 9:02:00)
用C語言做開發(fā),開發(fā)速度是快,但寫出的代碼稍不留心,就做成一個大胖子了.在嵌入式應(yīng)用中,有時很關(guān)注成本與性價比,往往希望能在性價比上找到平衡點,代碼尺寸的優(yōu)化就顯得很重要了.
當(dāng)然,針對熟悉的8位51單片機(jī),大家都知道的方法和原則我先列幾個,不在討論之列
俺常用的瘦身密絕
1.能用unsignedchar的不用unsingedint,依些類推到ulong
2.能定義到data空間的不用定義到idata,更不要定義到Xdata
3........
哈哈,大家補(bǔ)充.

網(wǎng)友評論:全局變量不要用到中斷應(yīng)該不會出現(xiàn)預(yù)想不到的效果.


網(wǎng)友評論:有時代碼速度和代碼空間是能二者兼得的.俺就遇到過一類段代碼,貼出來給大家看看.
下面是新的代碼,采用聯(lián)合體拆解數(shù)據(jù).

uint8SD_read_sector(uint32addr,uint8xdata*Buffer)
//****************************************************************************
{

uint8idataCMD[6];
unionSDSector
{
uint32ulAddress;
uint8ucADDByte[4];
}CurrentSDSector;

CMD[0]=0X51;
CMD[4]=0X00;
CMD[5]=0XFF;

addr=addr<<9;//addr=addr*512
CurrentSDSector.ulAddress=addr;

CMD[1]=CurrentSDSector.ucADDByte[0];
CMD[2]=CurrentSDSector.ucADDByte[1];
CMD[3]=CurrentSDSector.ucADDByte[2];

returnSD_Read_Block(CMD,Buffer);
}

下面是老的代碼,用的是程序變換,不僅占空間,而且費時間,但看起來較容易理解,可讀性貌視很好.

uint8SD_read_sector(uint32addr,uint8*Buffer)
//****************************************************************************
{
uint8CMD[]={0x51,0x00,0x00,0x00,0x00,0xFF};

addr=addr<<9;//addr=addr*512

CMD[1]=((addr&0xFF000000)>>24);
CMD[2]=((addr&0x00FF0000)>>16);
CMD[3]=((addr&0x0000FF00)>>8);

returnSD_Read_Block(CMD,Buffer,512);

}


網(wǎng)友評論:比如32位arm,uint(32bit)自增自減比uchar自增自減快,因為uchar是uint做自增自減再做位屏蔽得到的

網(wǎng)友評論:但必須設(shè)置好訪問原則,否則很容易出亂

網(wǎng)友評論:首先說明,數(shù)組名并不是指針.所以也就不能說什么為什么把數(shù)組和指針獨立起來的問題了.數(shù)組名的內(nèi)涵在于它所指向的實體是一種數(shù)據(jù)結(jié)構(gòu),而這種數(shù)據(jù)結(jié)構(gòu)就是--數(shù)組.數(shù)組名的外延在于它可以轉(zhuǎn)換為指向它所指代的實體的指針,而且是一個常量指針(ps:11樓).而且我們常說的指向數(shù)組的指針又是另一種變量類型了,它僅僅意味著數(shù)組存放的地址而已.
另外需要格外注意的是:數(shù)組名作為函數(shù)形參時,在函數(shù)體內(nèi),它失去了本身的內(nèi)涵,徹底成為一個指針,并且它也失去了他的常量特性(也就是說,它可以自加,自減,可以被修改).(我們不能總是相信教科書上的東西,學(xué)校只能教我們要怎么做,具體怎么做要自己學(xué)習(xí))
20樓的說法是對的,為了避免作用域的無限膨脹,我們要在妥善處理信息的同時盡量縮短變量的生存周期.而且,這也是為了便于維護(hù)和方便別人閱讀代碼.在C++中更要注意這樣的問題.

網(wǎng)友評論:良好的結(jié)構(gòu)、可維護(hù)性>..效率>.....實現(xiàn)難度>.>.....................................................................................................................................................................代碼優(yōu)化

大部分情況,代碼優(yōu)化是由編譯器去做的事情,換個編譯器多塊好省;
還有部分情況,是由單片機(jī)廠商做的事情,加點FLASH不值什么錢;


網(wǎng)友評論:編譯器有時對愚蠢的(換言之,不太高效)的程序?qū)懛ㄊ菬o能為力的.

網(wǎng)友評論:指針對元素的操作,尤其是遍歷操作非常高效.
俺猜想可能是指針編譯時使用了高效的匯編尋址中的基址變址來實現(xiàn)內(nèi)存操作有關(guān).
數(shù)組單元的尋址應(yīng)變是基地址+偏移量為每一個數(shù)組單元的訪問尋址的吧.

網(wǎng)友評論:別老拿單片機(jī)說事,量大怎么怎么樣,真正有多少人能做稱的上量的東西?大部分電工做的東西能上多少量,能到100psc不?

就大部分東西來說(壇子里討論的那些),一個單片機(jī)能占成本的比例很小。有時連個接插件都比不上,為幾毛錢把自己折騰的死去活來,何必呢。

非常贊同3L,做大事不拘小節(jié)。

網(wǎng)友評論:事實上,更小的代碼未必就是沒有了可讀性!
很多地方還得對編譯器特性細(xì)節(jié)的把握.
比如關(guān)于指針和數(shù)組的問題.
在KEILC下,可是數(shù)組的代碼效率高于指針.

這么好的論題,怎么沒有看見兩位高手:dengm和hotpower參加呢?

網(wǎng)友評論:在函數(shù)中使用多個指針變量,往往編譯出來代碼量更大!

網(wǎng)友評論:使用switchcase時,ifelse判斷復(fù)雜條件時,應(yīng)該盡量增加冗余代碼,提高幾個判斷條件的相似度?梢灶惐葦(shù)字邏輯電路的卡諾圖優(yōu)化。

網(wǎng)友評論:如果用好的算法來查表,就不說了。
對于用簡單查表,就沒有switch好,尤其是當(dāng)case很多的情況下,尤其是case值離散的情況下。

網(wǎng)友評論:51單片機(jī)內(nèi)存就有好幾種,有dataidatapdataxdatacode,通用指針需要對所有情況都做兼容,效率是會打折扣.

網(wǎng)友評論:良好的架構(gòu);合理的類型聲明;指針的正確使用;最優(yōu)的算法實現(xiàn);任務(wù)的分配;對內(nèi)存使用的正確理解;另外相矛盾的全局變量,短地址最好,但是對實現(xiàn)程序良好和封裝和移植卻矛盾。。。?醋霎a(chǎn)品吧

網(wǎng)友評論:在c文件中被調(diào)用函數(shù)寫在前面而不再寫函數(shù)聲明,編譯出來的代碼量會小一點。不知新版的keil是否也這樣?

網(wǎng)友評論:倒是在沒有參數(shù)的地方用void明確化更有效
Demo:
voidmain(void)
{
}

網(wǎng)友評論:剛拿出N年前寫的跑馬demo程序,把主函數(shù)main放到文件最后面,這樣,其所調(diào)用的函數(shù)都在其前面定義編譯后data=20.0,code=2318。

再做一個實驗,把主函數(shù)main放到文件的所有函數(shù)定義的前面,main中調(diào)用的函數(shù)在其后定義,文件頭部寫上這些函數(shù)的原型,編譯后data=20.0,code=2326。

前后對比,代碼量少了8bytes!用keilv8.05a編譯的。

網(wǎng)友評論:很多細(xì)節(jié)的地方都會影響到C51的code大小。對于無需傳遞函數(shù)或無需返回值的函數(shù)使用void關(guān)鍵字,也是一個好習(xí)慣

網(wǎng)友評論:你說的情況也可能代碼變大,只是你運氣好,是因為程序中有很多跳轉(zhuǎn)指令,KEIL自動優(yōu)化成SJMP,AJMP,LJMP.

網(wǎng)友評論:學(xué)習(xí)學(xué)習(xí)
同意樓主的想法
有時候我們會為了達(dá)到目的
而忽略的代碼的大小

網(wǎng)友評論:具體原因沒有仔細(xì)研究,但代碼中沒有查表,也沒有g(shù)oto語句,純粹是while(1)中幾個函數(shù)順序調(diào)用,展現(xiàn)不同的流水燈效果。

網(wǎng)友評論:我也發(fā)現(xiàn)這個問題,即使在8.X里面

網(wǎng)友評論:順序:

正確性,
健壯性,
可讀性,

最后才是代碼尺寸何運行速度

網(wǎng)友評論:同意LS,沒有保證正確性、穩(wěn)定性、可讀性及可測性之前,
所謂代碼大小都是浮云

網(wǎng)友評論:比如以下函數(shù),用C51寫與卡交換數(shù)據(jù)時多半要用到,如何優(yōu)化,希望大家提出自己的想法.
unsignedlongSwapINT32(unsignedlongdData)
{
dData=((dData&0xff)<<24)|((dData&0xff00)<<8)|((dData&0xff000000)>>24)|((dData&0xff0000)>>8);

returndData;
}

網(wǎng)友評論:其實寫程序,看著是寫代碼,

實際上是:

抽象現(xiàn)實問題為邏輯表達(dá),
有的時候為了所謂的效率,復(fù)用,
過渡追求代碼大小,運行效率
反而會造成過渡抽象,結(jié)果會隱含錯誤.


其實寫程序,前人總結(jié)的無非是:

高內(nèi)聚,低耦合,模塊功能要單純,


模塊內(nèi)部緊密聯(lián)系,
外部出入口條件要少,
完成一個單純的功能.





網(wǎng)友評論:程序結(jié)構(gòu)--代碼復(fù)用算法--專用算法代替通用算法

專用法代替通用算法就把可移植給弄死了.

個人覺得還是向著"高內(nèi)聚,低耦合,模塊功能要單純"走要好.碰上PIC16C54這樣的不如直接上匯編算了.
再碰上PIC16F73這樣的,先按上面的走,到時裝不下了,找占用最大的下手,如果還差較多就直接換芯片得了,誰知到時要加個小功能,就整死了,不如干脆直接換上大的.
所以現(xiàn)在搞的就很喜歡ATMEGA16與ATMEGA32這樣的芯片用,小的不行,后面還有個大的等著你用.硬件電路一點也不用改


網(wǎng)友評論:
就跟玩游戲一樣,先把等級提高了,到時武器再慢慢去練的好.要不然再好的武器裝備在新人身上也發(fā)揮不了大功效,反而傷了自已可就麻煩了.

壇內(nèi)新人還是較多,期待樓上及樓上高人開壇傳授碼程序如何做到"高內(nèi)聚,低耦合,模塊功能要單純"及硬件無關(guān)大法.

網(wǎng)友評論:個人認(rèn)為硬件無關(guān)大法就用OS


網(wǎng)友評論:學(xué)習(xí)

網(wǎng)友評論:unsignedlongSwapINT32(unsignedlongdData)
{
unionBigLongValue
{
ulongulReturnValue;
ucharucByte[4];
}CurrentBigLongValue;

uchar*ucData;

ucData=(uchar*)&dData;
CurrentBigLongValue.ucByte[3]=*ucData++;
CurrentBigLongValue.ucByte[2]=*ucData++;
CurrentBigLongValue.ucByte[1]=*ucData++;
CurrentBigLongValue.ucByte[0]=*ucData++;

returnCurrentBigLongValue.ulReturnValue;
}

此函數(shù)雖然節(jié)省空間,但與編譯器對整型變量的大小端約定關(guān)聯(lián),故移植時尤其要注意編譯壞境的約定.

網(wǎng)友評論:現(xiàn)在的重點是優(yōu)化代碼,其它的肯定也會考慮的

比如以下函數(shù),用C51寫與卡交換數(shù)據(jù)時多半要用到,如何優(yōu)化,希望大家提出自己的想法.
unsignedlongSwapINT32(unsignedlongdData)
{
dData=((dData&0xff)<<24)|((dData&0xff00)<<8)|((dData&0xff000000)>>24)|((dData&0xff0000)>>8);

returndData;
}




網(wǎng)友評論:7樓你好:青椒一下為什么計數(shù)器盡量用減法啊

網(wǎng)友評論:減法運算會生成DJNZ指令,效率高.

網(wǎng)友評論:unsignedlongSwapINT32(unsignedlongdData)
{
#if0
dData=((dData&0xff)<<24)|((dData&0xff00)<<8)|
((dData&0xff000000)>>24)|((dData&0xff0000)>>8);

#else
unsignedlongtemp=dData;
unsignedchar*P=&temp;

((unsignedchar*)&dData)[0]=((unsignedchar*)&temp[3];
((unsignedchar*)&dData)[1]=((unsignedchar*)&temp[2];
((unsignedchar*)&dData)[2]=((unsignedchar*)&temp[1];
((unsignedchar*)&dData)[3]=((unsignedchar*)&temp[0];
#endif
returndData;
}
這種寫法可以節(jié)省68字節(jié),應(yīng)該還有更好的,期待能有更好的出來!

網(wǎng)友評論:unsignedlongSwapINT32(u32dData)
{
//dData=((dData&0xff)<<24)|((dData&0xff00)<<8)|
//((dData&0xff000000)>>24)|((dData&0xff0000)>>8);

unsignedcharbuf,buf1;

buf=((unsignedchar*)&dData)[1];
buf1=((unsignedchar*)&dData)[0];

((unsignedchar*)&dData)[0]=((unsignedchar*)&dDat[3];
((unsignedchar*)&dData)[1]=((unsignedchar*)&dDat[2];
((unsignedchar*)&dData)[2]=buf;
((unsignedchar*)&dData)[3]=buf1;

}
比最原始的寫法節(jié)省94個字節(jié),編譯平臺KEILC51,期待更好的!

網(wǎng)友評論:俺來試試效果,挑戰(zhàn)自我的精神值得表揚(yáng)呀!

網(wǎng)友評論:95:unsignedlongSwapINT32(unsignedlongdData)
C:0x076C8F61MOV0x61,R7
C:0x076E8E60MOV0x60,R6
C:0x07708D5FMOV0x5F,R5
C:0x07728C5EMOV?_PRINTF517?BYTE(0x5E),R4
100:unsignedcharbuf,buf1;
101:
102:buf=((unsignedchar*)&dData)[1];
C:0x0774AF5FMOVR7,0x5F
103:buf1=((unsignedchar*)&dData)[0];
104:
C:0x0776AE5EMOVR6,?_PRINTF517?BYTE(0x5E)
105:((unsignedchar*)&dData)[0]=((unsignedchar*)&dData)[3];
C:0x077885615EMOV?_PRINTF517?BYTE(0x5E),0x61
106:((unsignedchar*)&dData)[1]=((unsignedchar*)&dData)[2];
C:0x077B85605FMOV0x5F,0x60
107:((unsignedchar*)&dData)[2]=buf;
C:0x077E8F60MOV0x60,R7
108:((unsignedchar*)&dData)[3]=buf1;
109:
C:0x07808E61MOV0x61,R6
110:}
111:#endif
112:
C:0x078222RET

網(wǎng)友評論:包含返回代碼部分,用C要想高效還是傳遞指針最好,可以通過指針直接修改原始數(shù)據(jù),節(jié)省了大量的數(shù)據(jù)傳遞時間,那樣應(yīng)該和匯編效率不相上下.

原代碼
unsignedlongSwapINT32(unsignedlongdData)
{
//dData=((dData&0xff)<<24)|((dData&0xff00)<<8)|
//((dData&0xff000000)>>24)|((dData&0xff0000)>>8);

union{
U8b[4];
U32x;
}temp;

temp.b[3]=((U8*)&dData)[0];
temp.b[2]=((U8*)&dData)[1];
temp.b[1]=((U8*)&dData)[2];
temp.b[0]=((U8*)&dData)[3];

returntemp.x;
}
編譯效果
;#defineU8unsignedchar
;#defineU16unsignedint
;#defineU32unsignedlong
;
;
;unsignedlongSwapINT32(unsignedlongdData)

RSEG?PR?_SwapINT32?MAIN
_SwapINT32:
USING0
;SOURCELINE#130
MOVdData?141+03H,R7
MOVdData?141+02H,R6
MOVdData?141+01H,R5
MOVdData?141,R4
;{
;SOURCELINE#131
;//dData=((dData&0xff)<<24)|((dData&0xff00)<<8)|
;//((dData&0xff000000)>>24)|((dData&0xff0000)>>8);
;
;union{
;U8b[4];
;U32x;
;}temp;
;
;temp.b[3]=((U8*)&dData)[0];
;SOURCELINE#140
MOVtemp?142+03H,dData?141
;temp.b[2]=((U8*)&dData)[1];
;SOURCELINE#141
MOVtemp?142+02H,dData?141+01H
;temp.b[1]=((U8*)&dData)[2];
;SOURCELINE#142
MOVtemp?142+01H,dData?141+02H
;temp.b[0]=((U8*)&dData)[3];
;SOURCELINE#143
MOVtemp?142,dData?141+03H
;
;returntemp.x;
;SOURCELINE#145
MOVR7,temp?142+03H
MOVR6,temp?142+02H
MOVR5,temp?142+01H
MOVR4,temp?142
;}
;SOURCELINE#146
?C0020:
RET
;ENDOF_SwapINT32

END

網(wǎng)友評論:ayb_ICE的測試結(jié)果如圖

網(wǎng)友評論:
相關(guān)鏈接:/upfiles/img/20097/2009712104759742.rar

網(wǎng)友評論:函數(shù)完成的功能實際上就是將入口處R4.R5,R6,R7的內(nèi)容變換成R7,R6,R5,R4然后返回上層主調(diào)函數(shù)

理論上最優(yōu)化的偽碼為
MOVACC,R4
XCHR7,ACC
MOVACC,R6
XCHR5,ACC
RET

如何引導(dǎo)Keil編譯器使用XCH指令,不得其解.

網(wǎng)友評論:74L的沒有寫返回語句,所有小了4條匯編指令語句,用C不可能寫出交換寄存器的語句
理由如下:
  如果對某個局部變量進(jìn)行強(qiáng)制指針變換,那么這個變量不可能被分配給寄存器,因為寄存器的取決于當(dāng)前的寄存器組,而這個函數(shù)要想高效必須進(jìn)行指針變換.
  實際是這個函數(shù)的功能不復(fù)雜,語句也少,要想用C寫最好傳遞一個或兩個具體指針參數(shù),然后利用指針進(jìn)行數(shù)據(jù)交換,不用返回數(shù)據(jù),傳遞具體指針也比傳遞U32數(shù)據(jù)效率要高,局部變量也可以被分配給寄存器,這樣效率是很高的.指針方式也比用匯編的參數(shù)傳遞和返回參數(shù)方式要高效的多.此處用于傳遞參數(shù)的時間已經(jīng)超過了數(shù)據(jù)處理的核心時間了...


網(wǎng)友評論:源代碼
#defineU32unsignedlong
#defineU8unsignedchar

#definemacro_SwapINT32(src,des)
{
((U8*)&src)[0]=((U8*)&des)[3];
((U8*)&src)[1]=((U8*)&des)[2];
((U8*)&src)[2]=((U8*)&des)[1];
((U8*)&src)[3]=((U8*)&des)[0];
}

voidtest(void)
{
U32x,y;

macro_SwapINT32(x,y);
}
編譯效果
;#definemacro_SwapINT32(src,des)
;{
;((U8*)&src)[0]=((U8*)&des)[3];
;((U8*)&src)[1]=((U8*)&des)[2];
;((U8*)&src)[2]=((U8*)&des)[1];
;((U8*)&src)[3]=((U8*)&des)[0];
;}
;
;voidtest(void)

RSEG?PR?test?MAIN
test:
USING0
;SOURCELINE#106
;{
;SOURCELINE#107
;U32x,y;
;SOURCELINE#108
;
;macro_SwapINT32(x,y);
;SOURCELINE#110
MOVx?141,y?142+03H
MOVx?141+01H,y?142+02H
MOVx?141+02H,y?142+01H
MOVx?141+03H,y?142
;}
;SOURCELINE#111
RET
;ENDOFtest

END


網(wǎng)友評論:abc-ice有81樓提出的宏變換的確是高效而又簡潔的風(fēng)格,值得大家學(xué)習(xí).

網(wǎng)友評論:顯得不夠聰明,明顯的字節(jié)返回值在R7里是不合理的做法,因為對返回值的判斷時還是要把R7賦給ACC,如果直通過ACC傳遞返回效率會高很多,本身ACC的效率就比RX要高,這些可能是歷史原因造成的.

網(wǎng)友評論:看了這么多,學(xué)到不少東西。繼續(xù)學(xué)習(xí)!

網(wǎng)友評論:如果函數(shù)返回值是一個uchar,的確應(yīng)該用ACC返回.還好位變量是用進(jìn)位位C返回,效率較高.
印象中Keil早期也是給人做OEM生產(chǎn)的.

網(wǎng)友評論:謝謝大家各抒已見
從宏觀上提出的辦法網(wǎng)友已給出了最佳答案
1.程序結(jié)構(gòu)--代碼復(fù)用
2.算法--專用算法代替通用算法

從微觀上來解決,很多網(wǎng)友已給出了速度又快,代碼尺寸又小的演示程序,只要用心優(yōu)化,總能做得更好!

哈哈,如果大家喜歡,可以開展下一個議題.

網(wǎng)友評論:1:能否把“高內(nèi)聚,低耦合,模塊功能要單純”這個說法做個詳細(xì)的闡述呢?
2:宏觀上,程序結(jié)構(gòu)--代碼復(fù)用;算法--專用算法代替通用算法。能再細(xì)致的總結(jié)一下嗎?怎么個代碼復(fù)用,什么樣的是專用算法,什么樣的是通用算法。
3:可不可以將微觀上的代碼優(yōu)化方法把大家討論的做個總結(jié)呢?讓我這個萊鳥也能享受一下前輩們的勞動成果呵呵。。。。

我是萊鳥,問題有點菜,不要笑我哦!期待中


網(wǎng)友評論:還是小點好,特別是低價位的

瀏覽:(1955)| 評論( 0 )
博文評論

  • 昵 稱:
  • 內(nèi) 容:10~250個字符
  • 驗證碼: 驗證碼看不清楚?請點擊刷新驗證碼
  •                      
  • 博文分類

    熱點博文

    最新博文

    最新評論

    IC電子元件查詢
    IC郵購網(wǎng)電子元件品質(zhì)保障