国产精品一区二区三区毛片淫片,国产成人久久久精品一区,91欧美视频网站http://www.bjzhda.cnzh-cn曙海教育集團(tuán)論壇http://www.bjzhda.cnRss Generator By Dvbbs.Netofficeoffice@126.comimages/logo.gif曙海教育集團(tuán)論壇關(guān)于F2812中用C語(yǔ)言來(lái)實(shí)現(xiàn)中斷的說(shuō)明http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2414&Page=1wangxinxin2010-12-10 12:04:35關(guān)于F2812中用C語(yǔ)言來(lái)實(shí)現(xiàn)中斷的說(shuō)明:
1.首先在.cmd中定位系統(tǒng)中斷表:
MEMORY
{
PAGE 0 :
......................................
PAGE 1 :
......................................
PIE_VECT : origin = 0x000D00, length = 0x000100

7 @' f# G+ T1 g

......................................
}


SECTIONS
{
...................................
PieVectTable : > PIE_VECT, PAGE = 1
.....................................
}
2.在C中制定該中斷的結(jié)構(gòu)體:
#pragma DATA_SECTION(PieVectTable,"PieVectTable");
struct PIE_VECT_TABLE PieVectTable;(在DSP28_GlobalVariableDefs.C中初始化)
3.用一組常數(shù)(按照中斷向量的順序)初始化該名字為PIE_VECT_TABLE的表:
typedef interrupt void(*PINT)(void);這里有些一問(wèn),一下應(yīng)該為函數(shù)名??

) M. w, G3 ^+ v) c* h e5 o

// Define Vector Table:
struct PIE_VECT_TABLE {

: y5 r# r' m( }4 F# \! d! _7 z

// Reset is never fetched from this table.
// It will always be fetched from 0x3FFFC0 in either
// boot ROM or XINTF Zone 7 depending on the state of
// the XMP/MC input signal. On the F2810 it is always
// fetched from boot ROM.

8 r: r, N5 P. b" o$ J2 C6 ]

PINT PIE1_RESERVED;
PINT PIE2_RESERVED;
PINT PIE3_RESERVED;
PINT PIE4_RESERVED;
PINT PIE5_RESERVED;
PINT PIE6_RESERVED;
PINT PIE7_RESERVED;
PINT PIE8_RESERVED;
PINT PIE9_RESERVED;
PINT PIE10_RESERVED;
PINT PIE11_RESERVED;
PINT PIE12_RESERVED;
PINT PIE13_RESERVED;

% ^! U6 d* R6 Q9 ?

// Non-Peripheral Interrupts:
PINT XINT13; // XINT13
PINT TINT2; // CPU-Timer2
PINT DATALOG; // Datalogging interrupt
PINT RTOSINT; // RTOS interrupt
PINT EMUINT; // Emulation interrupt
PINT XNMI; // Non-maskable interrupt
PINT ILLEGAL; // Illegal operation TRAP
PINT USER0; // User Defined trap 0
PINT USER1; // User Defined trap 1
PINT USER2; // User Defined trap 2
PINT USER3; // User Defined trap 3
PINT USER4; // User Defined trap 4
PINT USER5; // User Defined trap 5
PINT USER6; // User Defined trap 6
PINT USER7; // User Defined trap 7
PINT USER8; // User Defined trap 8
PINT USER9; // User Defined trap 9
PINT USER10; // User Defined trap 10
PINT USER11; // User Defined trap 11

// Group 1 PIE Peripheral Vectors:
PINT PDPINTA; // EV-A
PINT PDPINTB; // EV-B
PINT rsvd1_3;
PINT XINT1;
PINT XINT2;
PINT ADCINT; // ADC
PINT TINT0; // Timer 0
PINT WAKEINT; // WD

// Group 2 PIE Peripheral Vectors:
PINT CMP1INT; // EV-A
PINT CMP2INT; // EV-A
PINT CMP3INT; // EV-A
PINT T1PINT; // EV-A
PINT T1CINT; // EV-A
PINT T1UFINT; // EV-A
PINT T1OFINT; // EV-A
PINT rsvd2_8;

// Group 3 PIE Peripheral Vectors:
PINT T2PINT; // EV-A
PINT T2CINT; // EV-A
PINT T2UFINT; // EV-A
PINT T2OFINT; // EV-A
PINT CAPINT1; // EV-A
PINT CAPINT2; // EV-A
PINT CAPINT3; // EV-A
PINT rsvd3_8;

// Group 4 PIE Peripheral Vectors:
PINT CMP4INT; // EV-B
PINT CMP5INT; // EV-B
PINT CMP6INT; // EV-B
PINT T3PINT; // EV-B
PINT T3CINT; // EV-B
PINT T3UFINT; // EV-B
PINT T3OFINT; // EV-B
PINT rsvd4_8;

// Group 5 PIE Peripheral Vectors:
PINT T4PINT; // EV-B
PINT T4CINT; // EV-B
PINT T4UFINT; // EV-B
PINT T4OFINT; // EV-B
PINT CAPINT4; // EV-B
PINT CAPINT5; // EV-B
PINT CAPINT6; // EV-B
PINT rsvd5_8;

# c" P/ a, `' g. t' Y' V: l

// Group 6 PIE Peripheral Vectors:
PINT SPIRXINTA; // SPI-A
PINT SPITXINTA; // SPI-A
PINT rsvd6_3;
PINT rsvd6_4;
PINT MRINTA; // McBSP-A
PINT MXINTA; // McBSP-A
PINT rsvd6_7;
PINT rsvd6_8;

// Group 7 PIE Peripheral Vectors:
PINT rsvd7_1;
PINT rsvd7_2;
PINT rsvd7_3;
PINT rsvd7_4;
PINT rsvd7_5;
PINT rsvd7_6;
PINT rsvd7_7;
PINT rsvd7_8;

) X+ e1 w- d" o% S5 `1 h# o

// Group 8 PIE Peripheral Vectors:
PINT rsvd8_1;
PINT rsvd8_2;
PINT rsvd8_3;
PINT rsvd8_4;
PINT rsvd8_5;
PINT rsvd8_6;
PINT rsvd8_7;
PINT rsvd8_8;

. n) v4 d; T, }9 H% Y7 l7 K

// Group 9 PIE Peripheral Vectors:
PINT RXAINT; // SCI-A
PINT TXAINT; // SCI-A
PINT RXBINT; // SCI-B
PINT TXBINT; // SCI-B
PINT ECAN0INTA; // eCAN
PINT ECAN1INTA; // eCAN
PINT rsvd9_7;
PINT rsvd9_8;

: F: C6 l( m* Y) x

// Group 10 PIE Peripheral Vectors:
PINT rsvd10_1;
PINT rsvd10_2;
PINT rsvd10_3;
PINT rsvd10_4;
PINT rsvd10_5;
PINT rsvd10_6;
PINT rsvd10_7;
PINT rsvd10_8;

// Group 11 PIE Peripheral Vectors:
PINT rsvd11_1;
PINT rsvd11_2;
PINT rsvd11_3;
PINT rsvd11_4;
PINT rsvd11_5;
PINT rsvd11_6;
PINT rsvd11_7;
PINT rsvd11_8;

' R0 L2 H0 L4 M e- X0 p

// Group 12 PIE Peripheral Vectors:
PINT rsvd12_1;
PINT rsvd12_2;
PINT rsvd12_3;
PINT rsvd12_4;
PINT rsvd12_5;
PINT rsvd12_6;
PINT rsvd12_7;
PINT rsvd12_8;
};
然后在使我們?cè)?cmd文件中定義的表有以上屬性:
extern struct PIE_VECT_TABLE PieVectTable;(在.h文件中)
4.初始化該表(在.c文件中)使之能夠?yàn)橹鞒绦蛩褂茫?br/>const struct PIE_VECT_TABLE PieVectTableInit = {

0 e/ r* {5 P7 u k. \7 a

PIE_RESERVED, // Reserved space
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,

# T& u6 w: U0 R# J! j


// Non-Peripheral Interrupts
INT13_ISR, // XINT13 or CPU-Timer 1
INT14_ISR, // CPU-Timer2
DATALOG_ISR, // Datalogging interrupt
RTOSINT_ISR, // RTOS interrupt
EMUINT_ISR, // Emulation interrupt
NMI_ISR, // Non-maskable interrupt
ILLEGAL_ISR, // Illegal operation TRAP
USER0_ISR, // User Defined trap 0
USER1_ISR, // User Defined trap 1
USER2_ISR, // User Defined trap 2
USER3_ISR, // User Defined trap 3
USER4_ISR, // User Defined trap 4
USER5_ISR, // User Defined trap 5
USER6_ISR, // User Defined trap 6
USER7_ISR, // User Defined trap 7
USER8_ISR, // User Defined trap 8
USER9_ISR, // User Defined trap 9
USER10_ISR, // User Defined trap 10
USER11_ISR, // User Defined trap 11

: N' }3 w, d# q7 r

// Group 1 PIE Vectors
PDPINTA_ISR, // EV-A
PDPINTB_ISR, // EV-B
rsvd_ISR,
XINT1_ISR,
XINT2_ISR,
ADCINT_ISR, // ADC
TINT0_ISR, // Timer 0
WAKEINT_ISR, // WD

_4 }) S" s$ N( k+ k( `5 R# l' T$ @

// Group 2 PIE Vectors
CMP1INT_ISR, // EV-A
CMP2INT_ISR, // EV-A
CMP3INT_ISR, // EV-A
T1PINT_ISR, // EV-A
T1CINT_ISR, // EV-A
T1UFINT_ISR, // EV-A
T1OFINT_ISR, // EV-A
rsvd_ISR,

// Group 3 PIE Vectors
T2PINT_ISR, // EV-A
T2CINT_ISR, // EV-A
T2UFINT_ISR, // EV-A
T2OFINT_ISR, // EV-A
CAPINT1_ISR, // EV-A
CAPINT2_ISR, // EV-A
CAPINT3_ISR, // EV-A
rsvd_ISR,

// Group 4 PIE Vectors
CMP4INT_ISR, // EV-B
CMP5INT_ISR, // EV-B
CMP6INT_ISR, // EV-B
T3PINT_ISR, // EV-B
T3CINT_ISR, // EV-B
T3UFINT_ISR, // EV-B
T3OFINT_ISR, // EV-B
rsvd_ISR,

// Group 5 PIE Vectors
T4PINT_ISR, // EV-B
T4CINT_ISR, // EV-B
T4UFINT_ISR, // EV-B
T4OFINT_ISR, // EV-B
CAPINT4_ISR, // EV-B
CAPINT5_ISR, // EV-B
CAPINT6_ISR, // EV-B
rsvd_ISR,

( A( Z, `9 g8 I, i% t% ~: L2 E

// Group 6 PIE Vectors
SPIRXINTA_ISR, // SPI-A
SPITXINTA_ISR, // SPI-A
rsvd_ISR,
rsvd_ISR,
MRINTA_ISR, // McBSP-A
MXINTA_ISR, // McBSP-A
rsvd_ISR,
rsvd_ISR,

// Group 7 PIE Vectors
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,

+ I( b) D4 S' a5 W

// Group 8 PIE Vectors
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,

// Group 9 PIE Vectors
SCIRXINTA_ISR, // SCI-A
SCITXINTA_ISR, // SCI-A
SCIRXINTB_ISR, // SCI-B
SCITXINTB_ISR, // SCI-B
ECAN0INTA_ISR, // eCAN
ECAN1INTA_ISR, // eCAN
rsvd_ISR,
rsvd_ISR,

// Group 10 PIE Vectors
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,

// Group 11 PIE Vectors
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,

9 c$ u# B O8 L e- J# ]

// Group 12 PIE Vectors
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
rsvd_ISR,
};

$ l; q3 G X) h) K+ y


//---------------------------------------------------------------------------
// InitPieVectTable:
//---------------------------------------------------------------------------
// This function initializes the PIE vector table to a known state.
// This function must be executed after boot time.
//

6 I6 S1 Q9 M4 Q) a/ g$ L

void InitPieVectTable(void)
{
int16 i;
Uint32 *Source = (void *) &圖片點(diǎn)擊可在新窗口打開查看ieVectTableInit;
Uint32 *Dest = (void *) &圖片點(diǎn)擊可在新窗口打開查看ieVectTable;

EALLOW;
for(i=0; i < 128; i++)
*Dest++ = *Source++;
EDIS;

[/ t; }+ q! a6 n9 W/ |

// Enable the PIE Vector Table
PieCtrl.PIECRTL.bit.ENPIE = 1;

}
5.中斷服務(wù)程序:
讓以上的數(shù)值指向你所要的服務(wù)程序,例如:
PieVectTable.TINT2 = &ISRTimer2;
那么,ISRTimer2也就成了中斷服務(wù)程序,
×××切記:一定要在主程序的開始先聲明該程序:
interrupt void ISRTimer2(void);

6 U |2 W: o" G; N* r" {/ S# v* C

.............
.............
然后按照您的需要編制該程序:
interrupt void ISRTimer2(void)
{
CpuTimer2.InterruptCount++;
}

" z. p8 _* J1 d% v6 t8 q. o: W$ p]]>
C語(yǔ)言編譯過(guò)程總結(jié)詳解http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2413&Page=1wangxinxin2010-12-10 11:48:31 

圖片點(diǎn)擊可在新窗口打開查看

 

從圖上可以看到,整個(gè)代碼的編譯過(guò)程分為編譯和鏈接兩個(gè)過(guò)程,編譯對(duì)應(yīng)圖中的大括號(hào)括起的部分,其余則為鏈接過(guò)程。
 

編譯過(guò)程


 

編譯過(guò)程又可以分成兩個(gè)階段:編譯和會(huì)匯編。


 

編譯


 

       編譯是讀取源程序(字符流),對(duì)之進(jìn)行詞法和語(yǔ)法的分析,將高級(jí)語(yǔ)言指令轉(zhuǎn)換為功能等效的匯編代碼,源文件的編譯過(guò)程包含兩個(gè)主要階段:


 

       第一個(gè)階段是預(yù)處理階段,在正式的編譯階段之前進(jìn)行。預(yù)處理階段將根據(jù)已放置在文件中的預(yù)處理指令來(lái)修改源文件的內(nèi)容。如#include指令就是一個(gè)預(yù)處理指令,它把頭文件的內(nèi)容添加到.cpp文件中。這個(gè)在編譯之前修改源文件的方式提供了很大的靈活性,以適應(yīng)不同的計(jì)算機(jī)和操作系統(tǒng)環(huán)境的限制。一個(gè)環(huán)境需要的代碼跟另一個(gè)環(huán)境所需的代碼可能有所不同,因?yàn)榭捎玫挠布虿僮飨到y(tǒng)是不同的。在許多情況下,可以把用于不同環(huán)境的代碼放在同一個(gè)文件中,再在預(yù)處理階段修改代碼,使之適應(yīng)當(dāng)前的環(huán)境。
 


 

主要是以下幾方面的處理:


 

(1)宏定義指令,如 #define a  b
對(duì)于這種偽指令,預(yù)編譯所要做的是將程序中的所有a用b替換,但作為字符串常量的 a則不被替換。還有 #undef,則將取消對(duì)某個(gè)宏的定義,使以后該串的出現(xiàn)不再被替換。


 

(2)條件編譯指令,如#ifdef,#ifndef,#else,#elif,#endif等。
這些偽指令的引入使得程序員可以通過(guò)定義不同的宏來(lái)決定編譯程序?qū)δ男┐a進(jìn)行處理。預(yù)編譯程序?qū)⒏鶕?jù)有關(guān)的文件,將那些不必要的代碼過(guò)濾掉
   
(3) 頭文件包含指令,如#include "FileName"或者#include <FileName>等。
在頭文件中一般用偽指令#define定義了大量的宏(最常見(jiàn)的是字符常量),同時(shí)包含有各種外部符號(hào)的聲明。采用頭文件的目的主要是為了使某些定義可以供多個(gè)不同的C源程序使用。因?yàn)樵谛枰玫竭@些定義的C源程序中,只需加上一條#include語(yǔ)句即可,而不必再在此文件中將這些定義重復(fù)一遍。預(yù)編譯程序?qū)杨^文件中的定義統(tǒng)統(tǒng)都加入到它所產(chǎn)生的輸出文件中,以供編譯程序?qū)χM(jìn)行處理。包含到c源程序中的頭文件可以是系統(tǒng)提供的,這些頭文件一般被放在 /usr/include目錄下。在程序中#include它們要使用尖括號(hào)(<>)。另外開發(fā)人員也可以定義自己的頭文件,這些文件一般與 c源程序放在同一目錄下,此時(shí)在#include中要用雙引號(hào)("")。
   
(4)特殊符號(hào),預(yù)編譯程序可以識(shí)別一些特殊的符號(hào)。
例如在源程序中出現(xiàn)的LINE標(biāo)識(shí)將被解釋為當(dāng)前行號(hào)(十進(jìn)制數(shù)),F(xiàn)ILE則被解釋為當(dāng)前被編譯的C源程序的名稱。預(yù)編譯程序?qū)τ谠谠闯绦蛑谐霈F(xiàn)的這些串將用合適的值進(jìn)行替換。
   
       預(yù)編譯程序所完成的基本上是對(duì)源程序的“替代”工作。經(jīng)過(guò)此種替代,生成一個(gè)沒(méi)有宏定義、沒(méi)有條件編譯指令、沒(méi)有特殊符號(hào)的輸出文件。這個(gè)文件的含義同沒(méi)有經(jīng)過(guò)預(yù)處理的源文件是相同的,但內(nèi)容有所不同。下一步,此輸出文件將作為編譯程序的輸出而被翻譯成為機(jī)器指令。
   
       第二個(gè)階段編譯、優(yōu)化階段,經(jīng)過(guò)預(yù)編譯得到的輸出文件中,只有常量;如數(shù)字、字符串、變量的定義,以及C語(yǔ)言的關(guān)鍵字,如main,if,else,for,while,{,}, +,-,*,\等等。
   
       編譯程序所要作得工作就是通過(guò)詞法分析和語(yǔ)法分析,在確認(rèn)所有的指令都符合語(yǔ)法規(guī)則之后,將其翻譯成等價(jià)的中間代碼表示或匯編代碼。
   
       優(yōu)化處理是編譯系統(tǒng)中一項(xiàng)比較艱深的技術(shù)。它涉及到的問(wèn)題不僅同編譯技術(shù)本身有關(guān),而且同機(jī)器的硬件環(huán)境也有很大的關(guān)系。優(yōu)化一部分是對(duì)中間代碼的優(yōu)化。這種優(yōu)化不依賴于具體的計(jì)算機(jī)。另一種優(yōu)化則主要針對(duì)目標(biāo)代碼的生成而進(jìn)行的。
   
       對(duì)于前一種優(yōu)化,主要的工作是刪除公共表達(dá)式、循環(huán)優(yōu)化(代碼外提、強(qiáng)度削弱、變換循環(huán)控制條件、已知量的合并等)、復(fù)寫傳播,以及無(wú)用賦值的刪除,等等。

       后一種類型的優(yōu)化同機(jī)器的硬件結(jié)構(gòu)密切相關(guān),最主要的是考慮是如何充分利用機(jī)器的各個(gè)硬件寄存器存放的有關(guān)變量的值,以減少對(duì)于內(nèi)存的訪問(wèn)次數(shù)。另外,如何根據(jù)機(jī)器硬件執(zhí)行指令的特點(diǎn)(如流水線、RISC、CISC、VLIW等)而對(duì)指令進(jìn)行一些調(diào)整使目標(biāo)代碼比較短,執(zhí)行的效率比較高,也是一個(gè)重要的研究課題。
   
匯編
   
      匯編實(shí)際上指把匯編語(yǔ)言代碼翻譯成目標(biāo)機(jī)器指令的過(guò)程。對(duì)于被翻譯系統(tǒng)處理的每一個(gè)C語(yǔ)言源程序,都將最終經(jīng)過(guò)這一處理而得到相應(yīng)的目標(biāo)文件。目標(biāo)文件中所存放的也就是與源程序等效的目標(biāo)的機(jī)器語(yǔ)言代碼。目標(biāo)文件由段組成。通常一個(gè)目標(biāo)文件中至少有兩個(gè)段:


代碼段:該段中所包含的主要是程序的指令。該段一般是可讀和可執(zhí)行的,但一般卻不可寫。


 

數(shù)據(jù)段:主要存放程序中要用到的各種全局變量或靜態(tài)的數(shù)據(jù)。一般數(shù)據(jù)段都是可讀,可寫,可執(zhí)行的。
 


 

UNIX環(huán)境下主要有三種類型的目標(biāo)文件:


 

(1)可重定位文件
其中包含有適合于其它目標(biāo)文件鏈接來(lái)創(chuàng)建一個(gè)可執(zhí)行的或者共享的目標(biāo)文件的代碼和數(shù)據(jù)。


 

(2)共享的目標(biāo)文件

這種文件存放了適合于在兩種上下文里鏈接的代碼和數(shù)據(jù)。第一種是鏈接程序可把它與其它可重定位文件及共享的目標(biāo)文件一起處理來(lái)創(chuàng)建另一個(gè)目標(biāo)文件;
第二種是動(dòng)態(tài)鏈接程序?qū)⑺c另一個(gè)可執(zhí)行文件及其它的共享目標(biāo)文件結(jié)合到一起,創(chuàng)建一個(gè)進(jìn)程映象。


 

(3)可執(zhí)行文件
   
       它包含了一個(gè)可以被操作系統(tǒng)創(chuàng)建一個(gè)進(jìn)程來(lái)執(zhí)行之的文件。匯編程序生成的實(shí)際上是第一種類型的目標(biāo)文件。對(duì)于后兩種還需要其他的一些處理方能得到,這個(gè)就是鏈接程序的工作了。


 

鏈接過(guò)程

       由匯編程序生成的目標(biāo)文件并不能立即就被執(zhí)行,其中可能還有許多沒(méi)有解決的問(wèn)題。
   
       例如,某個(gè)源文件中的函數(shù)可能引用了另一個(gè)源文件中定義的某個(gè)符號(hào)(如變量或者函數(shù)調(diào)用等);在程序中可能調(diào)用了某個(gè)庫(kù)文件中的函數(shù),等等。所有的這些問(wèn)題,都需要經(jīng)鏈接程序的處理方能得以解決。
   
       鏈接程序的主要工作就是將有關(guān)的目標(biāo)文件彼此相連接,也即將在一個(gè)文件中引用的符號(hào)同該符號(hào)在另外一個(gè)文件中的定義連接起來(lái),使得所有的這些目標(biāo)文件成為一個(gè)能夠誒操作系統(tǒng)裝入執(zhí)行的統(tǒng)一整體。
   
       根據(jù)開發(fā)人員指定的同庫(kù)函數(shù)的鏈接方式的不同,鏈接處理可分為兩種:


 

(1)靜態(tài)鏈接
        在這種鏈接方式下,函數(shù)的代碼將從其所在地靜態(tài)鏈接庫(kù)中被拷貝到最終的可執(zhí)行程序中。這樣該程序在被執(zhí)行時(shí)這些代碼將被裝入到該進(jìn)程的虛擬地址空間中。靜態(tài)鏈接庫(kù)實(shí)際上是一個(gè)目標(biāo)文件的集合,其中的每個(gè)文件含有庫(kù)中的一個(gè)或者一組相關(guān)函數(shù)的代碼。


 

(2) 動(dòng)態(tài)鏈接
   
       在此種方式下,函數(shù)的代碼被放到稱作是動(dòng)態(tài)鏈接庫(kù)或共享對(duì)象的某個(gè)目標(biāo)文件中。鏈接程序此時(shí)所作的只是在最終的可執(zhí)行程序中記錄下共享對(duì)象的名字以及其它少量的登記信息。在此可執(zhí)行文件被執(zhí)行時(shí),動(dòng)態(tài)鏈接庫(kù)的全部?jī)?nèi)容將被映射到運(yùn)行時(shí)相應(yīng)進(jìn)程的虛地址空間。動(dòng)態(tài)鏈接程序?qū)⒏鶕?jù)可執(zhí)行程序中記錄的信息找到相應(yīng)的函數(shù)代碼。
   
       對(duì)于可執(zhí)行文件中的函數(shù)調(diào)用,可分別采用動(dòng)態(tài)鏈接或靜態(tài)鏈接的方法。使用動(dòng)態(tài)鏈接能夠使最終的可執(zhí)行文件比較短小,并且當(dāng)共享對(duì)象被多個(gè)進(jìn)程使用時(shí)能節(jié)約一些內(nèi)存,因?yàn)樵趦?nèi)存中只需要保存一份此共享對(duì)象的代碼。但并不是使用動(dòng)態(tài)鏈接就一定比使用靜態(tài)鏈接要優(yōu)越。在某些情況下動(dòng)態(tài)鏈接可能帶來(lái)一些性能上損害。
   
       我們?cè)趌inux使用的gcc編譯器便是把以上的幾個(gè)過(guò)程進(jìn)行捆綁,使用戶只使用一次命令就把編譯工作完成,這的確方便了編譯工作,但對(duì)于初學(xué)者了解編譯過(guò)程就很不利了,下圖便是gcc代理的編譯過(guò)程:

圖片點(diǎn)擊可在新窗口打開查看

從上圖可以看到:


 

預(yù)編譯
將.c 文件轉(zhuǎn)化成 .i文件
使用的gcc命令是:gcc –E
對(duì)應(yīng)于預(yù)處理命令cpp


 

編譯
將.c/.h文件轉(zhuǎn)換成.s文件
使用的gcc命令是:gcc –S
對(duì)應(yīng)于編譯命令   cc –S


 

匯編
將.s 文件轉(zhuǎn)化成 .o文件
使用的gcc 命令是:gcc –c
對(duì)應(yīng)于匯編命令是  as


 

鏈接
將.o文件轉(zhuǎn)化成可執(zhí)行程序
使用的gcc 命令是: gcc
對(duì)應(yīng)于鏈接命令是  ld


 

       總結(jié)起來(lái)編譯過(guò)程就上面的四個(gè)過(guò)程:預(yù)編譯、編譯、匯編、鏈接。Lia了解這四個(gè)過(guò)程中所做的工作,對(duì)我們理解頭文件、庫(kù)等的工作過(guò)程是有幫助的,而且清楚的了解編譯鏈接過(guò)程還對(duì)我們?cè)诰幊虝r(shí)定位錯(cuò)誤,以及編程時(shí)盡量調(diào)動(dòng)編譯器的檢測(cè)錯(cuò)誤會(huì)有很大的幫助的。

]]>
各位對(duì)C語(yǔ)言結(jié)構(gòu)中成員的對(duì)齊(alignment)怎樣理解?http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2412&Page=1wangxinxin2010-12-10 11:47:29zp1 zp2 zp4 zp8 zp16 sizeof(member) \--------------------------------------- 1 | 0 0 0 0 0 2 | 0 2 2 2 2 4 | 0 2 4 4 4 8 | 0 2 4 8 8 16 | 0 2 4 8 16 x | aligned to largest member 看一段代碼: #include #include typedef struct memo_el { char date[9]; struct memo_el *prev,*next; int ref_number; char sex; } memo; main( ) { printf( "Offset of %s is %d\n", "date", offsetof( memo, date ) ); printf( "Offset of %s is %d\n", "prev", offsetof( memo, prev ) ); printf( "Offset of %s is %d\n", "next", offsetof( memo, next ) ); printf( "Offset of %s is %d\n", "ref_number", offsetof( memo, ref_number ) ); printf( "Offset of %s is %d\n", "sex", offsetof( memo, sex ) ); printf( "Size of %s is %d\n", "memo", sizeof( memo ) ); printf( "Number of padding bytes is %d\n", sizeof( memo ) - (offsetof( memo, sex ) + sizeof( char )) ); return 0; } 輸出: 16位zp1:(毫無(wú)疑問(wèn)) Offset of date is 0 Offset of prev is 9 Offset of next is 11 Offset of ref_number is 13 Offset of sex is 15 Size of memo is 16 Number of padding bytes is 0 16位 zp2、4、8結(jié)果都一樣: Offset of date is 0 Offset of prev is 10 Offset of next is 12 Offset of ref_number is 14 Offset of sex is 16 Size of memo is 18 Number of padding bytes is 1 如果再把成員改一個(gè)長(zhǎng)整類型, typedef struct memo_el { char date[9]; struct memo_el *prev,*next; long int ref_number; char sex; } memo; 結(jié)果在16位ZP2-8都是這樣: Offset of date is 0 Offset of prev is 10 Offset of next is 12 Offset of ref_number is 16 Offset of sex is 20 Size of memo is 24 Number of padding bytes is 3 現(xiàn)在我無(wú)法解釋了~]]>16道嵌入式C語(yǔ)言面試題http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2411&Page=1wangxinxin2010-12-10 11:45:341. 用預(yù)處理指令#define 聲明一個(gè)常數(shù),用以表明1年中有多少秒(忽略閏年問(wèn)題)

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在這想看到幾件事情:
1). #define 語(yǔ)法的基本知識(shí)(例如:不能以分號(hào)結(jié)束,括號(hào)的使用,等等)
2). 懂得預(yù)處理器將為你計(jì)算常數(shù)表達(dá)式的值,因此,直接寫出你是如何計(jì)算一年中有多少秒而不是計(jì)算出實(shí)際的值,是更清晰而沒(méi)有代價(jià)的。
3). 意識(shí)到這個(gè)表達(dá)式將使一個(gè)16位機(jī)的整型數(shù)溢出-因此要用到長(zhǎng)整型符號(hào)L,告訴編譯器這個(gè)常數(shù)是的長(zhǎng)整型數(shù)。
4). 如果你在你的表達(dá)式中用到UL(表示無(wú)符號(hào)長(zhǎng)整型),那么你有了一個(gè)好的起點(diǎn)。記住,第一印象很重要。


2. 寫一個(gè)“標(biāo)準(zhǔn)”宏MIN,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。


#define MIN(A,B) ((A) <= (B) (A) : (B))
這個(gè)測(cè)試是為下面的目的而設(shè)的:
1). 標(biāo)識(shí)#define在宏中應(yīng)用的基本知識(shí)。這是很重要的,因?yàn)橹钡角度?inline)操作符變?yōu)闃?biāo)準(zhǔn)C的一部分,宏是方便產(chǎn)生嵌入代碼的唯一方法,對(duì)于嵌入式系統(tǒng)來(lái)說(shuō),為了能達(dá)到要求的性能,嵌入代碼經(jīng)常是必須的方法。
2). 三重條件操作符的知識(shí)。這個(gè)操作符存在C語(yǔ)言中的原因是它使得編譯器能產(chǎn)生比if-then-else更優(yōu)化的代碼,了解這個(gè)用法是很重要的。
3). 懂得在宏中小心地把參數(shù)用括號(hào)括起來(lái)
4). 我也用這個(gè)問(wèn)題開始討論宏的副作用,例如:當(dāng)你寫下面的代碼時(shí)會(huì)發(fā)生什么事?
least = MIN(*p++, b);

3. 預(yù)處理器標(biāo)識(shí)#error的目的是什么?

如果你不知道答案,請(qǐng)看參考文獻(xiàn)1。這問(wèn)題對(duì)區(qū)分一個(gè)正常的伙計(jì)和一個(gè)書呆子是很有用的。只有書呆子才會(huì)讀C語(yǔ)言課本的附錄去找出象這種
問(wèn)題的答案。當(dāng)然如果你不是在找一個(gè)書呆子,那么應(yīng)試者最好希望自己不要知道答案。

死循環(huán)(Infinite loops)

4. 嵌入式系統(tǒng)中經(jīng)常要用到無(wú)限循環(huán),你怎么樣用C編寫死循環(huán)呢?

這個(gè)問(wèn)題用幾個(gè)解決方案。我首選的方案是:
while(1) { }
一些程序員更喜歡如下方案:
for(;;) { }
這個(gè)實(shí)現(xiàn)方式讓我為難,因?yàn)檫@個(gè)語(yǔ)法沒(méi)有確切表達(dá)到底怎么回事。如果一個(gè)應(yīng)試者給出這個(gè)作為方案,我將用這個(gè)作為一個(gè)機(jī)會(huì)去探究他們這樣做的
基本原理。如果他們的基本答案是:“我被教著這樣做,但從沒(méi)有想到過(guò)為什么。”這會(huì)給我留下一個(gè)壞印象。
第三個(gè)方案是用 goto
Loop:
...
goto Loop;
應(yīng)試者如給出上面的方案,這說(shuō)明或者他是一個(gè)匯編語(yǔ)言程序員(這也許是好事)或者他是一個(gè)想進(jìn)入新領(lǐng)域的BASIC/FORTRAN程序員。

數(shù)據(jù)聲明(Data declarations)

5. 用變量a給出下面的定義
a) 一個(gè)整型數(shù)(An integer)
b) 一個(gè)指向整型數(shù)的指針(A pointer to an integer)
c) 一個(gè)指向指針的的指針,它指向的指針是指向一個(gè)整型數(shù)(A pointer to a pointer to an integer)
d) 一個(gè)有10個(gè)整型數(shù)的數(shù)組(An array of 10 integers)
e) 一個(gè)有10個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù)的(An array of 10 pointers to integers)
f) 一個(gè)指向有10個(gè)整型數(shù)數(shù)組的指針(A pointer to an array of 10 integers)
g) 一個(gè)指向函數(shù)的指針,該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù)(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一個(gè)有10個(gè)指針的數(shù)組,該指針指向一個(gè)函數(shù),該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù) ( An array of ten pointers to functions that take an integer argument and return an integer )

答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer


人們經(jīng)常聲稱這里有幾個(gè)問(wèn)題是那種要翻一下書才能回答的問(wèn)題,我同意這種說(shuō)法。當(dāng)我寫這篇文章時(shí),為了確定語(yǔ)法的正確性,我的確查了一下書。
但是當(dāng)我被面試的時(shí)候,我期望被問(wèn)到這個(gè)問(wèn)題(或者相近的問(wèn)題)。因?yàn)樵诒幻嬖嚨倪@段時(shí)間里,我確定我知道這個(gè)問(wèn)題的答案。應(yīng)試者如果不知道
所有的答案(或至少大部分答案),那么也就沒(méi)有為這次面試做準(zhǔn)備,如果該面試者沒(méi)有為這次面試做準(zhǔn)備,那么他又能為什么出準(zhǔn)備呢?


Static

6. 關(guān)鍵字static的作用是什么?

這個(gè)簡(jiǎn)單的問(wèn)題很少有人能回答完全。在C語(yǔ)言中,關(guān)鍵字static有三個(gè)明顯的作用:
1). 在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變。
2). 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量。
3). 在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
大多數(shù)應(yīng)試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個(gè)應(yīng)試者的嚴(yán)重的缺點(diǎn),因?yàn)樗@然不懂得本地化數(shù)據(jù)和代碼范圍的好處和重要性。


Const

7.關(guān)鍵字const是什么含意?
我 只要一聽(tīng)到被面試者說(shuō):“const意味著常數(shù)”,我就知道我正在和一個(gè)業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有 用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應(yīng)該非常熟悉const能做什么和不能做什么.如果你從沒(méi)有讀到那篇文章,只要能說(shuō)出const意味著“只讀”就可以了。盡管這個(gè)答案不是完全的答案,但我接受它作為一個(gè)正確的答案。(如果你想知道更詳細(xì)的答案,仔細(xì)讀一下Saks的文章吧。)如果應(yīng)試者能正確回答這個(gè)問(wèn)題,我將問(wèn)他一個(gè)附加的問(wèn)題:下面的聲明都是什么意思?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)。如果應(yīng)試者能正確回答這些問(wèn)題,那么他就給我留下了一個(gè)好印象。順帶提一句,也許你可能會(huì)問(wèn),即使不用關(guān)鍵字 const,也還是能很容易寫出功能正確的程序,那么我為什么還要如此看重關(guān)鍵字const呢?我也如下的幾下理由:
1). 關(guān)鍵字const 的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實(shí)際上,聲明一個(gè)參數(shù)為常量是為了告訴了用戶這個(gè)參數(shù)的應(yīng)用目的。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息。(當(dāng)然,懂得用const的程序員很少會(huì)留下的垃圾讓別人來(lái)清理的。)
2). 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
3). 合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無(wú)意的代碼修改。簡(jiǎn)而言之,這樣可以減少bug的出現(xiàn)。

Volatile

8. 關(guān)鍵字volatile有什么含意 并給出三個(gè)不同的例子。

一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:
1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
2). 一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)
3). 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量
回答不出這個(gè)問(wèn)題的人是不會(huì)被雇傭的。我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。嵌入式系統(tǒng)程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內(nèi)容將會(huì)帶來(lái)災(zāi)難。
假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑這否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
1). 一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
2). 一個(gè)指針可以是volatile 嗎?解釋為什么。
3). 下面的函數(shù)有什么錯(cuò)誤:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。
2). 是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
3). 這段代碼的有個(gè)惡作劇。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

位操作(Bit manipulation)

9. 嵌入式系統(tǒng)總是要用戶對(duì)變量或寄存器進(jìn)行位操作。給定一個(gè)整型變量a,寫兩段代碼,第一個(gè)設(shè)置a的bit 3,第二個(gè)清除a 的bit 3。在以上兩個(gè)操作中,要保持其它位不變。

對(duì)這個(gè)問(wèn)題有三種基本的反應(yīng)
1). 不知道如何下手。該被面者從沒(méi)做過(guò)任何嵌入式系統(tǒng)的工作。
2). 用bit fields。Bit fields是被扔到C語(yǔ)言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時(shí)也保證了的你的代碼是不可重用的。我最近不幸看到Infineon為其較復(fù)雜的通信芯片寫的驅(qū)動(dòng)程序,它用到了bit fields因此完全對(duì)我無(wú)用,因?yàn)槲业木幾g器用其它的方式 來(lái)實(shí)現(xiàn)bit fields的。從道德講:永遠(yuǎn)不要讓一個(gè)非嵌入式的家伙粘實(shí)際硬件的邊。
3). 用 #defines 和 bit masks 操作。這是一個(gè)有極高可移植性的方法,是應(yīng)該被用到的方法。最佳的解決方案如下:
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
一些人喜歡為設(shè)置和清除值而定義一個(gè)掩碼同時(shí)定義一些說(shuō)明常數(shù),這也是可以接受的。我希望看到幾個(gè)要點(diǎn):說(shuō)明常數(shù)、|=和&=~操作。

訪問(wèn)固定的內(nèi)存位置(Accessing fixed memory locations)

10. 嵌入式系統(tǒng)經(jīng)常具有要求程序員去訪問(wèn)某特定的內(nèi)存位置的特點(diǎn)。在某工程中,要求設(shè)置一絕對(duì)地址為0x67a9的整型變量的值為0xaa66。編譯器是一個(gè)純粹的ANSI編譯器。寫代碼去完成這一任務(wù)。

這一問(wèn)題測(cè)試你是否知道為了訪問(wèn)一絕對(duì)地址把一個(gè)整型數(shù)強(qiáng)制轉(zhuǎn)換(typecast)為一指針是合法的。這一問(wèn)題的實(shí)現(xiàn)方式隨著個(gè)人風(fēng)格不同而不同。典型的類似代碼如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;

一個(gè)較晦澀的方法是:
*(int * const)(0x67a9) = 0xaa55;

即使你的品味更接近第二種方案,但我建議你在面試時(shí)使用第一種方案。

中斷(Interrupts)

11. 中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開發(fā)商提供一種擴(kuò)展—讓標(biāo)準(zhǔn)C支持中斷。具代表事實(shí)是,產(chǎn)生了一個(gè)新的關(guān)鍵字 __interrupt。下面的代碼就使用了__interrupt關(guān)鍵字去定義了一個(gè)中斷服務(wù)子程序(ISR),請(qǐng)?jiān)u論一下這段代碼的。

__interrupt double compute_area (double radius)
{
     double area = PI * radius * radius;
     printf(" Area = %f", area);
     return area;
}

這個(gè)函數(shù)有太多的錯(cuò)誤了,以至讓人不知從何說(shuō)起了:
1). ISR 不能返回一個(gè)值。如果你不懂這個(gè),那么你不會(huì)被雇用的。
2). ISR 不能傳遞參數(shù)。如果你沒(méi)有看到這一點(diǎn),你被雇用的機(jī)會(huì)等同第一項(xiàng)。
3). 在許多的處理器/編譯器中,浮點(diǎn)一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點(diǎn)運(yùn)算。此外,ISR應(yīng)該是短而有效率的,在ISR中做浮點(diǎn)運(yùn)算是不明智的。
4). 與第三點(diǎn)一脈相承,printf()經(jīng)常有重入和性能上的問(wèn)題。如果你丟掉了第三和第四點(diǎn),我不會(huì)太為難你的。不用說(shuō),如果你能得到后兩點(diǎn),那么你的被雇用前景越來(lái)越光明了。

代碼例子(Code examples)
12 . 下面的代碼輸出是什么,為什么?

void foo(void)
{
     unsigned int a = 6;
     int b = -20;
     (a+b > 6) puts("> 6") : puts("<= 6");
}

這個(gè)問(wèn)題測(cè)試你是否懂得C語(yǔ)言中的整數(shù)自動(dòng)轉(zhuǎn)換原則,我發(fā)現(xiàn)有些開發(fā)者懂得極少這些東西。不管如何,這無(wú)符號(hào)整型問(wèn)題的答案是輸出是“>6”。原因是當(dāng)表達(dá)式中存在有符號(hào)類型和無(wú)符號(hào)類型時(shí)所有的操作數(shù)都自動(dòng)轉(zhuǎn)換為無(wú)符號(hào)類型。因此-20變成了一個(gè)非常大的正整數(shù),所以該表達(dá)式計(jì)算出的結(jié)果大于6。這一點(diǎn)對(duì)于應(yīng)當(dāng)頻繁用到無(wú)符號(hào)數(shù)據(jù)類型的嵌入式系統(tǒng)來(lái)說(shuō)是豐常重要的。如果你答錯(cuò)了這個(gè)問(wèn)題,你也就到了得不到這份工作的邊緣。

13. 評(píng)價(jià)下面的代碼片斷:

unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */

對(duì)于一個(gè)int型不是16位的處理器為說(shuō),上面的代碼是不正確的。應(yīng)編寫如下:

unsigned int compzero = ~0;

這一問(wèn)題真正能揭露出應(yīng)試者是否懂得處理器字長(zhǎng)的重要性。在我的經(jīng)驗(yàn)里,好的嵌入式程序員非常準(zhǔn)確地明白硬件的細(xì)節(jié)和它的局限,然而PC機(jī)程序往往把硬件作為一個(gè)無(wú)法避免的煩惱。
到了這個(gè)階段,應(yīng)試者或者完全垂頭喪氣了或者信心滿滿志在必得。如果顯然應(yīng)試者不是很好,那么這個(gè)測(cè)試就在這里結(jié)束了。但如果顯然應(yīng)試者做得不錯(cuò),那么我就扔出下面的追加問(wèn)題,這些問(wèn)題是比較難的,我想僅僅非常優(yōu)秀的應(yīng)試者能做得不錯(cuò)。提出這些問(wèn)題,我希望更多看到應(yīng)試者應(yīng)付問(wèn)題的方法,而不是答案。不管如何,你就當(dāng)是這個(gè)娛樂(lè)吧…

 

動(dòng)態(tài)內(nèi)存分配(Dynamic memory allocation)

 

14. 盡管不像非嵌入式計(jì)算機(jī)那么常見(jiàn),嵌入式系統(tǒng)還是有從堆(heap)中動(dòng)態(tài)分配內(nèi)存的過(guò)程的。那么嵌入式系統(tǒng)中,動(dòng)態(tài)分配內(nèi)存可能發(fā)生的問(wèn)題是什么?

這 里,我期望應(yīng)試者能提到內(nèi)存碎片,碎片收集的問(wèn)題,變量的持行時(shí)間等等。這個(gè)主題已經(jīng)在ESP雜志中被廣泛地討論過(guò)了(主要是 P.J. Plauger, 他的解釋遠(yuǎn)遠(yuǎn)超過(guò)我這里能提到的任何解釋),所有回過(guò)頭看一下這些雜志吧!讓應(yīng)試者進(jìn)入一種虛假的安全感覺(jué)后,我拿出這么一個(gè)小節(jié)目:下面的代碼片段的輸出是什么,為什么?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");

這是一個(gè)有趣的問(wèn)題。最近在我的一個(gè)同事不經(jīng)意把0值傳給了函數(shù)malloc,得到了一個(gè)合法的指針之后,我才想到這個(gè)問(wèn)題。這就是上面的代碼,該代碼的輸出是“Got a valid pointer”。我用這個(gè)來(lái)開始討論這樣的一問(wèn)題,看看被面試者是否想到庫(kù)例程這樣做是正確。得到正確的答案固然重要,但解決問(wèn)題的方法和你做決定的基本原理更重要些。

Typedef

15. Typedef 在C語(yǔ)言中頻繁用以聲明一個(gè)已經(jīng)存在的數(shù)據(jù)類型的同義字。也可以用預(yù)處理器做類似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;

以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個(gè)指向結(jié)構(gòu)s指針。哪種方法更好呢?(如果有的話)為什么?
這是一個(gè)非常微妙的問(wèn)題,任何人答對(duì)這個(gè)問(wèn)題(正當(dāng)?shù)脑颍┦菓?yīng)當(dāng)被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;

第一個(gè)擴(kuò)展為
struct s * p1, p2;

上面的代碼定義p1為一個(gè)指向結(jié)構(gòu)的指,p2為一個(gè)實(shí)際的結(jié)構(gòu),這也許不是你想要的。第二個(gè)例子正確地定義了p3 和p4 兩個(gè)指針。

]]>
用C語(yǔ)言描述數(shù)據(jù)結(jié)構(gòu)http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2410&Page=1wangxinxin2010-12-10 11:44:16- t8 D2 T/ B6 g6 |
在過(guò)去的一年之中,我對(duì)計(jì)算機(jī)的語(yǔ)言有了一個(gè)大體的了解,在前一段時(shí)間,我自學(xué)了數(shù)據(jù)結(jié)構(gòu),下面,談?wù)勎易詫W(xué)的數(shù)據(jù)結(jié)構(gòu)的看法,在接下來(lái)一段有人指點(diǎn)的時(shí)間里,再來(lái)糾正以前對(duì)數(shù)據(jù)結(jié)構(gòu)的錯(cuò)誤看法。; j0 G/ l! I! H9 g' D
數(shù)據(jù)結(jié)構(gòu)是一個(gè)比較抽象的東西,他的任務(wù)是從各種實(shí)際的問(wèn)題中歸納,抽象出個(gè)對(duì)象的特征,對(duì)象之間的相互關(guān)系,在選擇合適的數(shù)據(jù)結(jié)構(gòu)來(lái)組織,、儲(chǔ)存和選擇相應(yīng)的算法。其中,最重要的還是一種抽象思維的轉(zhuǎn)換,需要有一種歸納的思維,在初學(xué)的 時(shí)候,我選擇了在理解的基礎(chǔ)上背一些比較典型的數(shù)據(jù)結(jié)構(gòu),比如:線性表,隊(duì),餞的儲(chǔ)存方法等,最后發(fā)現(xiàn)一些其他的東西也可以類似。* c5 ?! A2 R+ y8 z: }3 r$ y
用C語(yǔ)言描述數(shù)據(jù)結(jié)構(gòu)可以分為以下幾部分:線性表,隊(duì),餞,廣義表,然后是樹,圖,最后還有遞歸,串,查找,排序。其中較為典型的例子有走迷宮,漢諾塔,出入隊(duì)列哈夫曼編碼等。
. q8 y1 h( Q7 M0 w/ B現(xiàn)行表示具有相同特征的數(shù)據(jù)元素的一個(gè)有限序列,儲(chǔ)存方式有兩種:順序儲(chǔ)存——順序表,鏈?zhǔn)絻?chǔ)存——鏈表。" _3 V) M4 |3 ^6 X
(一)順序表儲(chǔ)存結(jié)構(gòu),用C語(yǔ)言來(lái)運(yùn)行各個(gè)基本運(yùn)算的分類:
+ I5 m  C# h; ?- C4 iTypedef char ElemType          /*將字符性重新用ElemType來(lái)定義*/
' L  A, L9 e7 ^) ~: C( c#define MaxSize  99           /*用宏定義來(lái)定義MaxSize*/) n- t9 ~2 X7 S  c
Typedef struct8 ?# \+ s+ T$ {
{
2 r8 r! j& A7 f! X. W8 XElemType elem[MaxSize];      /*定義一種為SqList的結(jié)構(gòu)體類型*/
9 _, c6 o, `& P& E) Z, cInt length;
9 t- _8 C2 O$ E6 t0 E; `}SqList;" {  s- |( E* s9 ?- A" Q
(1)    初始化線性表0 D& d  J, ^  ]7 D: Q* e( W
Void InitList(SqList *&L)     /*將L定義為SqList類型*/
9 ]! x, g% q5 d! ?: r{4 Q2 e! a9 l* V2 `; J+ x
L=(Sqlist *)malloc(sizeof(SqList));   /*在內(nèi)存的動(dòng)態(tài)區(qū)分配一個(gè)長(zhǎng)度為n個(gè)
1 @1 R. {, Z0 \# [) @/ ~1 nL->length=0;                          長(zhǎng)為sizeof的連續(xù)空間*/
, t7 \% o3 u* J- B$ S6 l' V}! `( l, D+ O' b; I9 Q1 S9 M9 s  {
(2)    銷毀線性表
8 B( }2 G, [2 A2 j$ P        Void DestroyList(SqList *&L). g' ]; ?7 ~+ L4 J" Q# p5 U
{+ V) j+ O; a( V" }1 s  R9 m% a" D% [
Free(L);                          /*釋放L的儲(chǔ)存空間*/
0 w! b% l/ W0 }4 V9 X1 W}( @9 E4 `/ {* P1 H5 i0 v
(3)    判斷線性表是否為空3 W* _" k0 a  t* @4 f) w6 Q
Int ListEmpty(SqList *L)2 F  ~2 l# x% ^$ |, \9 v7 A/ o
{
: l1 M+ d! Q1 V) C3 n2 KReturn(L->length==0);( }8 m) _0 \' x! l( J6 x
}  S9 ?# U; z# I& r& n& s: H* ?- E
(4)    求線性表的長(zhǎng)度- Y: j3 O/ m4 w4 X' Q! q5 X3 v) e/ {
Int ListLength(SqList *L)' ^! z6 x. O) \$ h- ?0 N' \# U) n
{
1 t# y4 K0 R$ E  d2 c4 b: ?Return(L->length);! l7 P/ S# I+ ?) t" u  H. b/ s
}
' d2 Z0 l3 a& |' g2 S! m1 E. b# P(5)    輸出線性表5 O" _- U# S4 S, q1 J; i$ w
Void Displist(SqList *L)" ]- ~: P7 ~( z: _3 {. j
{) q$ J" K. E* N
int i;
* @; Z4 r$ ?5 n* R8 Yif(ListEmpty(L))
: _: l6 H4 U4 `+ [   return;" J) _5 i; C( }* X# |) Y8 n
for(i=0;i$ \0 U5 ^0 R- Q. n: a
printf(“%c,”L-elem);3 [; X0 n/ T7 i$ }% Y7 F6 B* l
printf(“\n”);
. U+ R$ c9 g, S1 l# {, f2 v! P}
3 g$ n& T0 G) r& b6 \9 |; c(6)    求線性表中某個(gè)數(shù)據(jù)元素得值: N0 Z7 K; ~9 w- F( N9 g/ c
比如求線性表的第i個(gè)元素的值e. r1 P  r1 ~2 D
int GetElem(SqList *L,int i,Elemtype e)     /*線性表L的第i個(gè)元素的值e*/
  _/ p+ \. T9 |  R{. d& P- X& H) n6 x
If(iL-length)
( B& t0 t/ z7 ~1 Y& eReturn 0;2 d5 ~; t; H2 L
else
3 ~, v( L* G, x      {( p8 H4 z5 a0 _4 b; X
       e=L->elem[i-1];
& J: {, C. v2 {, x( k8 L       return 1;* Q. G/ p+ l7 @0 @4 F
}                                                                                                        0 U. I' W- q0 f# ~2 q
(7)    按元素值查找(查找第一個(gè)與元素值相同的元素的位置)
3 b2 @$ b3 f' i4 E+ Cint Locateelem(SqList *L,Elemtype e)2 u2 A9 g, k& y7 \3 Y& ?+ u
{" M9 B1 a; a/ \+ P% o% w$ D. c
        int i=0;
' w- E' U" }* Q; e        while(ilength&&L->elem!=e)      /*i的值存在的范圍*/
9 i9 K7 f7 s! _! h  y. n. b- I               i++;$ z, p# B3 I- O# _" h# z
        if(i>=L-length)
: x. m5 ?0 F5 y2 h! x8 x- |9 y               return 0;4 n7 g5 \7 W4 v' o; `
        else
! h* M! B, R: t               return i+1;
3 B" b( ^  i. ^0 W6 R0 W}
# E+ c# L- P8 a2 T(8)    插入數(shù)據(jù)元素
' t, |3 o  C/ O: M; k% ~int ListInsert(SqList *L,int i,ElemType e)
) A1 x) Y/ O( ?- F; U{6 H" W3 j* W- L2 v+ V2 Y& G% s
       int j;
; l4 _( V. _# w       if(iL->length+1)
( X% P3 O  K9 @9 h              return 0;
: F1 o! a! m4 e: ]. Q       i--;4 I% c. w8 }9 N
       for(j=L->length;j>1;j--)
+ h, a- V, n3 V" N6 T5 R              L->elem[j]=L->elem[j-1];         /*首先出一個(gè)空的位子,然后前面的值依次4 M) J: T( V6 K5 V! @
       L->elem[e];                       覆蓋后面的值,即將前面的支附給后面的值*/
& n6 C, `. F+ n, z) `1 X       L->length++;
5 E* @6 t. t* T8 \5 S+ i       return 1;& p$ W' i) L+ z4 k
}
8 w& I% P' w$ u3 j7 U/ s6 m! f(9)刪除數(shù)據(jù)元素
+ H( i. ]9 F& I* iint ListDelete(SqList *L,int i,ElemType &e)' k. J9 [0 {  l  x; [
{1 |. M7 T* G* L6 Z# Y- I
       int j;
" `" I; D+ D* T6 L1 F       if(iL->length+1)
1 \, M9 K) x+ e8 n              return 0;
: o+ y6 d' G" r       i--;# @! Q) i, {6 [
       e=L->elem;# |( \/ P% I1 |; H6 u
       for(j=i;jlength-1;j++)
* s$ e' L* Q% v, p              L->elem[j]=L->elem[j+1];        /*與插入數(shù)據(jù)元素基本相似*/2 L' p+ k5 k, p
       L->length--;
  {7 n( T0 ?7 s% E6 @6 W# x       return 1;
# ?: l2 N' u0 K% B& m  @! g}
2 D: t# d$ n# l. ?; l5 A* l以上是數(shù)據(jù)結(jié)構(gòu)關(guān)于順序表的各種有關(guān)的儲(chǔ)存方式,與順序表對(duì)應(yīng)的是鏈表,它也是一種非常重要的儲(chǔ)存方式。  B) G% L; Q- P1 d
在初次接觸到c語(yǔ)言的時(shí)候已經(jīng)對(duì)鏈表有了大體的了解,它主要是由結(jié)點(diǎn)和指針域組成,指針指向下一個(gè)結(jié)點(diǎn)。3 l/ ~& [$ u. s# ^0 L
(二)單鏈表的運(yùn)算的實(shí)現(xiàn)
3 V% H! |; p2 H1 ^Typedef char ElemType
3 X7 q: Y& a( q; [  [: Q#define MaxSize 99+ {6 ^4 j- W  c) _! K) t. _* I" k9 a1 Y
Typedef struct LNode1 L* R; i4 Q0 o
{, ]8 W5 R; L- w4 g0 @  G' j
ElemType data;8 t5 F, v0 Z" I! t, K
struct LNode *next;
; A' R: B% j& ]9 o; s, `, p}LinkList;
  j" i2 ~* B% x(1)初始化線性表
7 P& R( L) ~- Y, Kvoid InitList(LinkList *&L)
$ p& W, [8 x* p$ [: R" v9 ?( P/ h8 j{+ F$ y* a6 x( i* ^  Z
       L=(Linklist *)malloc(sizeof(Linklist));     /*創(chuàng)建頭結(jié)點(diǎn)*/
7 Z4 t% S; e1 S* D" @7 x       L->next=NULL;
* e0 ?/ Z/ v4 b! G- J( j4 H8 q}
" C3 e7 ^* h) U1 o0 K3 k(2)銷毀線性表1 f0 y$ t" J9 m% W2 T5 }) q
Void DestroyList(LinkList *&L)1 P, G" ~3 G( G$ e# G
{, h3 l) f1 c' d3 A# p1 F8 t
       LinkList *p=L,q=L->next;           /*p位頭結(jié)點(diǎn),q為p的后繼結(jié)點(diǎn)*// O' {5 e' t3 \3 v; _5 y, g
       while(q!=NULL)
& X7 R! J' c2 u3 y; d% W. I) [& Z" Q- R       {0 a5 d3 K0 \' N' A& E5 s. d+ L
              free(p);  U6 z$ H: f3 X- I2 F6 ?# R
              p=q;                       /*p逐漸向后釋放*/; r3 Q0 d7 c9 u! q
              q=p-next;
7 d: U3 Y; k9 h# Vfree(p);                         /*釋放最后一個(gè)p*/8 b, ^0 f0 U4 Y+ s
}
# f7 n: L) q* ](3)判斷線性表是否為空?1 k! k6 v% d/ b! i' y1 u
int ListEmpty(LinkList *L)
# z  T" Q3 E& m9 z0 T2 Q9 h{
4 E2 F8 k( Q2 r/ E# O5 L: j       return(L->next==NULL)6 l# h9 o+ s5 w4 {/ I3 l
}" x* V* r& t9 T$ c0 x. f  M
]]>
沒(méi)有見(jiàn)過(guò)的c語(yǔ)言用法,求救http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2409&Page=1wangxinxin2010-12-10 11:39:46unsigned char IfInterTimeOK(tagInterTime * ptime) {
        if(ptime->ucDelay == 0) return 0;
    ptime->ucCount = (ptime->ucCount) + 1;
    if(ptime->ucCount >= ptime->ucDelay) {
            ptime->ucCount = 0;
        return 1;
    }
    return 0;
}
//-----------------------------------------------------------------
typedef struct {
        unsigned char ucDelay, ucCount;
}tagInterTime;                                                                        // Control the interface control time
unsigned char IfInterTimeOK(tagInterTime * ptime);// 1:Action OK
//---------------------------------------------------------------------------------
#define __INTERTIME_DECL(x, y)        SUBLIB_EXT tagInterTime g_it##x;  
#define __IT_START(x, y)                (g_it##x##.ucDelay = y, g_it##x##.ucCount = y)
#define __IT_STOP(x, y)                        g_it##x##.ucDelay = 0
#define __IT_OK(x, y)                        IfInterTimeOK(&g_it##x)
//------------------------------------------------------------------------------
#define IT_DECL(x)                                __INTERTIME_DECL(x)
#define IT_START(x)                                __IT_START(x)
#define IT_STOP(x)                                __IT_STOP(x)
#define IT_OK(x)                                __IT_OK(x)

#define AAA                        A, 25

下面這是用法,不知道是什么意思?
IT_START(AAA);   
if(IT_OK(AAA)) IT_START(AAA);
IT_STOP(AAA);
忘c(diǎn)語(yǔ)言高手指教一下
]]>
對(duì)C#開發(fā)的兩個(gè)基本原則的深入討論http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2408&Page=1wangxinxin2010-12-10 11:37:07
  明辨值類型和引用類型的使用場(chǎng)合

  這個(gè)條款討論的是類型設(shè)計(jì)時(shí)候的tradeoff——是將類型設(shè)計(jì)為結(jié)構(gòu)還是類。Bill Wagner先生給出了一個(gè)原則“值類型用于存儲(chǔ)數(shù)據(jù),引用類型用于定義行為(value types store values and reference types define behavior)”。

  如何判斷這個(gè)原則的適用性,Bill Wagner也給出了一個(gè)方法,那就是首先回答下面幾個(gè)問(wèn)題:

  1.該類型的主要職責(zé)是否用于數(shù)據(jù)存儲(chǔ)?

  2.該類型的公有接口是否都是一些存取屬性?

  3.是否確信該類型永遠(yuǎn)不可能有子類?

  4.是否確信該類型永遠(yuǎn)不可能具有多態(tài)行為?

  如果所有問(wèn)題的答案都是yes,那么就應(yīng)該采用值類型。這樣的判斷確實(shí)有很好的理由支撐,但是我個(gè)人認(rèn)為“將這4個(gè)問(wèn)題回答為yes”還不足以構(gòu)成采用值類型的全部理由。因?yàn)樵诤芏囗?xiàng)目實(shí)踐中,我發(fā)現(xiàn)值類型帶來(lái)的性能問(wèn)題不可小視。值類型帶來(lái)的性能問(wèn)題主要有兩個(gè):

  1.由于值類型實(shí)例在棧和托管堆之間的轉(zhuǎn)換而導(dǎo)致的box/unbox,以及由此帶來(lái)的托管堆上的垃圾。

  2.值類型默認(rèn)情況下采用的是值拷貝語(yǔ)義,如果是比較大的值類型,在傳遞參數(shù)和函數(shù)返回值時(shí),同樣會(huì)帶來(lái)性能問(wèn)題。

  關(guān)于第1條,Bill Wagner在本條款中提到了“引用類型會(huì)給垃圾收集器帶來(lái)負(fù)擔(dān)”這個(gè)表面看似正確的判斷。但是由于box/unbox的效應(yīng),有些情況下,反倒是值類型給垃圾收集器帶來(lái)了更多的負(fù)擔(dān)。比如將一些值類型放到一個(gè)集合中,然后又頻繁地對(duì)其進(jìn)行讀寫操作。如果碰到這種情況,我想“放棄結(jié)構(gòu)而采用類”未嘗不是一種更好的做法。事實(shí)上,將一個(gè)用作數(shù)據(jù)存儲(chǔ)的值類型(比如System.Drawing.Point)添加到一個(gè)集合(System.Collections.ArrayList)中是一個(gè)太常見(jiàn)不過(guò)的操作。不過(guò),C# 2.0中新引入的泛型技術(shù)對(duì)box/unbox的問(wèn)題有極大的改善。

  關(guān)于第2條,Scott Meyers先生在Effective C++的第22條“盡量使用pass-by-reference(傳址),少用pass-by-value(傳值)”中講的比較清楚。雖然由于C#中的結(jié)構(gòu)類型具有默認(rèn)的深拷貝語(yǔ)義,沒(méi)有拷貝構(gòu)造器的調(diào)用。而且結(jié)構(gòu)類型也沒(méi)有子類,因此在某種程度上來(lái)講不具有多態(tài)性,也就沒(méi)有C++對(duì)象傳值時(shí)可能出現(xiàn)的切割(slicing)效應(yīng)。但是值拷貝的成本仍然不小。尤其是在這個(gè)值類型比較大的情況下,問(wèn)題就比較嚴(yán)重。實(shí)際上,在.NET框架的Design Guidelines for Class Library Developers文檔中,在說(shuō)明什么時(shí)候應(yīng)該使用結(jié)構(gòu)類型的時(shí)候,其中提到了一項(xiàng)原則(還有其他一些并行原則)——類型實(shí)例數(shù)據(jù)的大小要小于16個(gè)字節(jié)。該文檔主要是從類型的運(yùn)行效率層面來(lái)考慮的,而Bill Wagner先生這里的條款主要是從類型的設(shè)計(jì)層面來(lái)考慮的。

  從上述兩條討論來(lái)看,我個(gè)人傾向于對(duì)結(jié)構(gòu)類型采取更為保守的設(shè)計(jì)策略。而對(duì)于類則可以積極大膽地使用。因?yàn)椤皩⒔Y(jié)構(gòu)類型不適當(dāng)?shù)卦O(shè)計(jì)為類”帶來(lái)的不良后果要遠(yuǎn)遠(yuǎn)小于“將類不適當(dāng)?shù)卦O(shè)計(jì)為結(jié)構(gòu)類型”所帶來(lái)的不良后果。就目前的經(jīng)驗(yàn)來(lái)看,我甚至認(rèn)為只有和非托管互操作打交道的情況才是使用結(jié)構(gòu)類型最充足的理由,其他情況都要“三思而后行”。當(dāng)然,在C# 2.0中引入泛型技術(shù)之后,box/unbox將不再是一個(gè)沉重的負(fù)擔(dān),應(yīng)付一些非常輕量級(jí)的場(chǎng)合,結(jié)構(gòu)類型依然有自己的一席之地。]]>
C語(yǔ)言實(shí)戰(zhàn)105例源碼--私藏很久的源碼http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2407&Page=1wangxinxin2010-12-10 11:35:15第1部分 基礎(chǔ)篇

實(shí)例1 一個(gè)價(jià)值“三天”的BUG 2
實(shí)例2 靈活使用遞增(遞減)操作符 5
實(shí)例3 算術(shù)運(yùn)算符計(jì)算器 7
實(shí)例4 邏輯運(yùn)算符計(jì)算器 9
實(shí)例5 IP地址解析 11
實(shí)例6 用if…else語(yǔ)句解決獎(jiǎng)金發(fā)放問(wèn)題 13
實(shí)例7 用for循環(huán)模擬自由落體 16
實(shí)例8 用while語(yǔ)句求n! 19
實(shí)例9 模擬銀行常用打印程序 22
實(shí)例10 使用一維數(shù)組統(tǒng)計(jì)選票 26
實(shí)例11 使用二維數(shù)組統(tǒng)計(jì)學(xué)生成績(jī) 29
實(shí)例12 簡(jiǎn)單的計(jì)算器 32
實(shí)例13 時(shí)鐘程序 35
實(shí)例14 華氏溫度和攝氏溫度的相互轉(zhuǎn)換 38
實(shí)例15 SimpleDebug函數(shù)應(yīng)用 40

第2部分 數(shù)值計(jì)算與數(shù)據(jù)結(jié)構(gòu)篇

實(shí)例16 常用的幾種排序方法 46
實(shí)例17 廣度優(yōu)先搜索及深度優(yōu)先搜索 53
實(shí)例18 實(shí)現(xiàn)基本的串操作 59
實(shí)例19 計(jì)算各點(diǎn)到源點(diǎn)的最短距離 62
實(shí)例20 儲(chǔ)油問(wèn)題 65
實(shí)例21 中獎(jiǎng)彩球問(wèn)題 67
實(shí)例22 0-1背包問(wèn)題 69
實(shí)例23 階梯計(jì)數(shù)問(wèn)題 72
實(shí)例24 二叉樹算法集 74
實(shí)例25 模擬LRU頁(yè)面置換算法 79
實(shí)例26 大整數(shù)階乘新思路 82
實(shí)例27 銀行事件驅(qū)動(dòng)模擬程序 84
實(shí)例28 模擬迷宮探路 87
實(shí)例29 實(shí)現(xiàn)高隨機(jī)度隨機(jī)序列 89
實(shí)例30 停車場(chǎng)管理系統(tǒng) 91

第3部分 文本屏幕與文件操作篇

實(shí)例31 菜單實(shí)現(xiàn) 96
實(shí)例32 窗口制作 97
實(shí)例33 模擬屏幕保護(hù)程序 100
實(shí)例34 文件讀寫基本操作 102
實(shí)例35 格式化讀寫文件 105
實(shí)例36 成塊讀寫操作 107
實(shí)例37 隨機(jī)讀寫文件 108
實(shí)例38 文件的加密和解密 111
實(shí)例39 實(shí)現(xiàn)兩個(gè)文件的連接 113
實(shí)例40 實(shí)現(xiàn)兩個(gè)文件信息的合并 116
實(shí)例41 文件信息統(tǒng)計(jì) 118
實(shí)例42 文件分割實(shí)例 121
實(shí)例43 同時(shí)顯示兩個(gè)文件的內(nèi)容 123
實(shí)例44 模擬Linux環(huán)境下的vi編輯器 124
實(shí)例45 文件操作綜合應(yīng)用——銀行賬戶管理 128

第4部分 病毒與安全篇

實(shí)例46 實(shí)用內(nèi)存清理程序 134
實(shí)例47 如何檢測(cè)Sniffer  136
實(shí)例48 加密DOS批處理程序 139
實(shí)例49 使用棧實(shí)現(xiàn)密碼設(shè)置 141
實(shí)例50 遠(yuǎn)程緩沖區(qū)溢出漏洞利用程序 144
實(shí)例51 簡(jiǎn)易漏洞掃描器 146
實(shí)例52 文件病毒檢測(cè)程序 149
實(shí)例53 監(jiān)測(cè)內(nèi)存泄露與溢出 150
實(shí)例54 實(shí)現(xiàn)traceroute命令 152
實(shí)例55 實(shí)現(xiàn)ping程序功能 154
實(shí)例56 獲取Linux本機(jī)IP地址 157
實(shí)例57 實(shí)現(xiàn)擴(kuò)展內(nèi)存的訪問(wèn) 161
實(shí)例58 隨機(jī)加密程序 164
實(shí)例59 MD5加密程序 165
實(shí)例60 RSA加密實(shí)例 168

第5部分 圖形篇

實(shí)例61 制作表格 172
實(shí)例62 用畫線函數(shù)作出的圖案 174
實(shí)例63 多樣的橢圓 176
實(shí)例64 多變的立方體 177
實(shí)例65 簡(jiǎn)易時(shí)鐘 178
實(shí)例66 跳動(dòng)的小球 181
實(shí)例67 用柱狀圖表示學(xué)生成績(jī)各分?jǐn)?shù)段比率 183
實(shí)例68 EGA/VGA屏幕存儲(chǔ) 187
實(shí)例69 按鈕制作 190
實(shí)例70 三維視圖制作 193
實(shí)例71 紅旗圖案制作 194
實(shí)例72 火焰動(dòng)畫制作 196
實(shí)例73 模擬水紋擴(kuò)散 199
實(shí)例74 彩色的Photo Frame  201
實(shí)例75 火箭發(fā)射演示 203

第6部分 系統(tǒng)篇

實(shí)例76 恢復(fù)內(nèi)存文本 208
實(shí)例77 挽救磁盤數(shù)據(jù) 210
實(shí)例78 建立和隱藏多個(gè)PRI DOS分區(qū) 213
實(shí)例79 簡(jiǎn)單的DOS下的中斷服務(wù)程序 216
實(shí)例80 文件名分析程序 219
實(shí)例81 鼠標(biāo)中斷處理 222
實(shí)例82 實(shí)現(xiàn)磁盤數(shù)據(jù)的整體加密 224
實(shí)例83 揭開CMOS密碼 227
實(shí)例84 獲取網(wǎng)卡信息 229
實(shí)例85 創(chuàng)建自己的設(shè)備 231
實(shí)例86 設(shè)置應(yīng)用程序啟動(dòng)密碼 233
實(shí)例87 獲取系統(tǒng)配置信息 236
實(shí)例88 硬件檢測(cè) 239
實(shí)例89 管道通信 241
實(shí)例90 程序自殺技術(shù)實(shí)現(xiàn) 244

第7部分 游戲篇

實(shí)例91 連續(xù)擊鍵游戲 248
實(shí)例92 擲骰子游戲 250
實(shí)例93 彈力球 252
實(shí)例94 俄羅斯方塊 253
實(shí)例95 24點(diǎn)撲克牌游戲 257
實(shí)例96 貪吃蛇 260
實(shí)例97 潛水艇大戰(zhàn) 262
實(shí)例98 機(jī)器人大戰(zhàn) 265
實(shí)例99 圖形模式下的搬運(yùn)工 266
實(shí)例100 十全十美游戲 269
第8部分 綜合篇
實(shí)例101 強(qiáng)大的通信錄 274
實(shí)例102 模擬Windows下UltraEdit程序 277
實(shí)例103 輕松實(shí)現(xiàn)個(gè)人理財(cái) 279
實(shí)例104 競(jìng)技比賽打分系統(tǒng) 281
實(shí)例105 火車訂票系統(tǒng) 286]]>
關(guān)于C和C++區(qū)別的討論http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2406&Page=1wangxinxin2010-12-10 11:20:17    我個(gè)人理解,這二者其實(shí)沒(méi)有太大差異性。

    C語(yǔ)言面向過(guò)程,OP,C++語(yǔ)言面向?qū)ο螅琌O.

    但實(shí)際上大家可能能關(guān)注到,不管如何OO,如何劃分類和對(duì)象,但是,具體到一個(gè)功能,還是要用函數(shù)來(lái)實(shí)現(xiàn),不管如何寫程序,到了函數(shù)內(nèi)部,其實(shí)還是那些if、for、while等等語(yǔ)句,還是面向過(guò)程的。

    所以,我和我的同事,平時(shí)并不會(huì)明顯去分辨C和C++的異同,在我們看來(lái),二者本來(lái)就是一體的。

    其實(shí)這個(gè)世界上,完全的OO是不存在的,當(dāng)我們實(shí)現(xiàn)一個(gè)功能的時(shí)候,很多時(shí)候,就是界定一些數(shù)據(jù),針對(duì)數(shù)據(jù)添加一些處理流程,獲得一個(gè)結(jié)果,這件事情,本質(zhì)上就是個(gè)過(guò)程。

    但C++還是很有用的。

    因?yàn)楹芏嗄暌郧,大家覺(jué)得傳統(tǒng)面向過(guò)程的語(yǔ)言,如C,如Basic,如Pascal,都有一個(gè)缺點(diǎn),就是在程序中,彼此暴露了太多的細(xì)節(jié),這造成各個(gè)功能之間,由于程序員的失誤,很容易發(fā)生粘連,聯(lián)系。換而言之,就算是非法訪問(wèn),通常也是合法而成功的,不會(huì)被編譯器檢查出來(lái)。比如C就允許全局變量和遠(yuǎn)指針調(diào)用。

    這在開發(fā)大型系統(tǒng)的時(shí)候,就出現(xiàn)了bug率居高不下,大型工程項(xiàng)目很難完成的缺點(diǎn)。

    正是因?yàn)榇耍蠹以谏鲜兰o(jì)七十年代,提出了模塊化開發(fā)的思想,試圖通過(guò)各個(gè)模塊的獨(dú)立開發(fā)和運(yùn)行,強(qiáng)行阻斷各個(gè)模塊不必要的耦合性,來(lái)達(dá)到讓程序穩(wěn)定的目的。

    但這樣畢竟是人工在操作,是人做的,就可能會(huì)犯錯(cuò)誤,大家覺(jué)得有必要在編譯器這一級(jí),要強(qiáng)調(diào)模塊之間的獨(dú)立性。

    這個(gè)時(shí)候,大家經(jīng)過(guò)分析,發(fā)現(xiàn)程序其實(shí)核心是和數(shù)據(jù)打交道的,一個(gè)數(shù)據(jù),業(yè)務(wù)上只要界定了用途,基本上,可能的訪問(wèn)方法就確定得差不多了,那么,我們有沒(méi)有可能,把一類數(shù)據(jù),以及其方法,從編譯器的角度區(qū)別開來(lái),構(gòu)建獨(dú)立模塊,外部模塊僅能訪問(wèn)到它允許訪問(wèn)的方法,其他的方法,全部報(bào)錯(cuò),拒絕編譯呢?

    答案是當(dāng)然可以。大家就這么做了。那么,我們看看,一類數(shù)據(jù)和其允許的方法的集合,就是對(duì)象啦,在這個(gè)思想上,OO,面向?qū)ο蟮乃枷刖彤a(chǎn)生了。

    最初,這個(gè)語(yǔ)言是一個(gè)新的語(yǔ)言,好像叫smalltalk吧,不過(guò),這個(gè)時(shí)候的語(yǔ)言,還是實(shí)驗(yàn)室產(chǎn)品,沒(méi)有投入商業(yè)運(yùn)營(yíng)。

    但這個(gè)時(shí)候,市場(chǎng)上,由于UNIX的推動(dòng),C語(yǔ)言基本上已經(jīng)一統(tǒng)天下了。很多人都學(xué)的C語(yǔ)言,讓大家去學(xué)習(xí)一門新語(yǔ)言,尤其是開發(fā)思路完全不同的語(yǔ)言,是不可想象的,成本太高。大家就想,能不能折中一下,以C的語(yǔ)法為藍(lán)本,開發(fā)一套OO的語(yǔ)言,C++就這么誕生了。

    其實(shí)OP到OO,C到C++,本質(zhì)上講,就是一個(gè)數(shù)據(jù)私有化的過(guò)程。甚至整個(gè)語(yǔ)言的發(fā)展史,也是一個(gè)數(shù)據(jù)私有化的過(guò)程。如匯編語(yǔ)言,其實(shí)是沒(méi)有私有數(shù)據(jù)的,所有的內(nèi)存都可以被訪問(wèn)。

    人們通過(guò)編譯器的界定和完善,逐漸實(shí)現(xiàn)數(shù)據(jù)私有化,最終的目標(biāo)就是實(shí)現(xiàn)一個(gè)軟件系統(tǒng)內(nèi)部各個(gè)模塊之間,高內(nèi)聚,低耦合的目標(biāo),最終保證程序員的產(chǎn)品質(zhì)量,進(jìn)而提高生產(chǎn)率。

    至于后面的泛型編程,多態(tài),繼承等等,無(wú)非是在這條路上繼續(xù)了一步而已,當(dāng)然,也是為了盡量減少程序員的代碼輸入量,進(jìn)一步提升生產(chǎn)效率而已。

    所以,從數(shù)據(jù)組織上講,C++比C先進(jìn)了一大步,但從功能實(shí)現(xiàn)上講,C++和C并無(wú)本質(zhì)不同。C++到現(xiàn)在,都不是一種完全的面向?qū)ο笳Z(yǔ)言,因?yàn)樗既匀槐A袅巳肿兞俊?/p>

    所以我的意見(jiàn),兩個(gè)一起學(xué),不要刻意去區(qū)分,好像用C就要用純C,沒(méi)必要。

    我們工程中,系統(tǒng)級(jí)的模塊組織,一般式C++的對(duì)象,每個(gè)單步功能,流程的實(shí)現(xiàn),我們都是C的函數(shù),僅僅是放在類里面而已

]]>
關(guān)于對(duì)c++基本語(yǔ)言的看法http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2405&Page=1wangxinxin2010-12-10 11:16:57也許寫這篇文章有的人會(huì)笑話我,都什么時(shí)候的年代了居然要談這個(gè)話題。是的我承認(rèn)有點(diǎn)老套了,原因是我畢業(yè)的時(shí)間太晚,接觸到的c++太晚。先前的自己一直以來(lái)就是認(rèn)為c語(yǔ)言真是個(gè)好東東,編程語(yǔ)言中其他語(yǔ)言不管多么上手,所么方便好用在我看來(lái)都不如c語(yǔ)言來(lái)的真實(shí),c語(yǔ)言是一種實(shí)在的語(yǔ)言,是一種你看得到,想的到,作的到的語(yǔ)言。之前我在青島的時(shí)候基本上接觸的是c語(yǔ)言,主要是在linux下的開發(fā),剛畢業(yè)的自己說(shuō)實(shí)話對(duì)c認(rèn)識(shí)太淺了,我掌握的是在linux下應(yīng)用程序的開發(fā),大部分用到了對(duì)文件的讀取,對(duì)指針的操作,而且自己都是在公司前輩的路下沿著開發(fā)的。自己根本就沒(méi)有真正的去認(rèn)真想想算法開發(fā)一個(gè)應(yīng)用程式。現(xiàn)在想來(lái)真是可悲的很,學(xué)習(xí)c語(yǔ)言如果自己不進(jìn)行程序的算法開發(fā),這是一個(gè)瞎子在路燈下亂逛,以為是找到了光明就可以跟正常人一樣,熟不知自己仍在無(wú)知中。所以之前對(duì)c的鐘情有些轉(zhuǎn)向,轉(zhuǎn)到了自己利用算法來(lái)實(shí)現(xiàn)功能的想法。

    為什么我第一段要講講c語(yǔ)言呢,因?yàn)閏語(yǔ)言是一切語(yǔ)言的基礎(chǔ),這好像是我大學(xué)時(shí)第一次接觸編程語(yǔ)言的老師跟我說(shuō)得一句話,如果c語(yǔ)言不能掌握,其他的語(yǔ)言肯定也不會(huì)好的,F(xiàn)在這我話我已經(jīng)深信不疑了,不管是java也好,c#也好還是最新的python等等語(yǔ)言吧,在我看來(lái)都是以c的基礎(chǔ)來(lái)進(jìn)行的,所謂的新無(wú)非是自己不用再想一些函數(shù)庫(kù)德算法了,我承認(rèn)這是一種進(jìn)步,至少是站在別人的肩膀上做事.效率的時(shí)代講究的也是效率這也正是講究效率開發(fā)公司對(duì)這些方便語(yǔ)言的鐘情。這是可以理解的事情。不過(guò)這里我要說(shuō)的是c++,這是真正的與c語(yǔ)言接觸緊密但是確實(shí)又非常實(shí)用的語(yǔ)言,人們都說(shuō)c++是個(gè)好東東,可是在開發(fā)的時(shí)候卻有時(shí)極力的回避這種語(yǔ)言,最終是因?yàn)閏語(yǔ)言的復(fù)雜性。說(shuō)句我個(gè)人的看法,我覺(jué)得這樣做是不對(duì)的,因?yàn)楦呖萍疾皇且恢写蟊娀闹R(shí),講究的是一個(gè)人或一個(gè)團(tuán)隊(duì)的智慧,就是因?yàn)閏++的復(fù)雜性就不去用它,或是少去用它而是用更多的方便開發(fā)語(yǔ)言,這種想法是不好的,因?yàn)槿绻粋(gè)搞程序的人對(duì)算法都不能很好的去自行開發(fā),只會(huì)是去沿用別人寫好的東西。充其量跟工廠里的機(jī)器裝配工很像,無(wú)非是把基本的一些寫好的類庫(kù)函數(shù)庫(kù)羅列好了。如果真是這樣這是軟件業(yè)的恥辱,也是中國(guó)軟件業(yè)的恥辱。

   很多時(shí)候都是在說(shuō)為什么人家外國(guó)的程序員都他媽的那么牛,一個(gè)個(gè)根爺爺?shù)乃频,寫得?biāo)準(zhǔn)也是好的,作的東西也是好的,就連出的代碼書也是好的。我想這里應(yīng)該有一定的原因吧。昨天把c++的基本課程設(shè)計(jì)的書看了一遍,發(fā)現(xiàn)c++如果真正的實(shí)用開發(fā),真是太帥了,不管是從代碼的羅列,思想的拓展。真是讓人感覺(jué)又一種耳目一新的感覺(jué)。c++的這種真正的面向?qū)ο笫且环N完美的結(jié)構(gòu),當(dāng)然世界上不可能有那么完美的語(yǔ)言。但是給我的感覺(jué)是一種思路的拓寬,讓我對(duì)程序的架構(gòu)有一種新的認(rèn)識(shí),可能是自己的編程語(yǔ)言基礎(chǔ)差,看了c++的基礎(chǔ)讓我感觸頗深,如果我寫得不像話,那還要請(qǐng)您對(duì)原諒畢竟我還是一個(gè)在不斷上升中的小小菜鳥,我接觸編程還不到2年,這里也就給我點(diǎn)鼓勵(lì),給您鞠躬了。

]]>
用C語(yǔ)言進(jìn)行CGI程序設(shè)計(jì)http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2404&Page=1wangxinxin2010-12-10 11:14:23作 者 : 肖治延

  CGI(公用網(wǎng)關(guān)接口)規(guī)定了Web服務(wù)器調(diào)用其他可執(zhí)行程序(CGI程 序)的接口協(xié)議標(biāo)準(zhǔn)。Web服務(wù)器通過(guò)調(diào)用CGI程序?qū)崿F(xiàn)和Web瀏覽器的交互,也就是CGI程序接受Web瀏覽器發(fā)送給Web服務(wù)器的信息,進(jìn)行處理,將響應(yīng)結(jié)果再回送給Web服務(wù)器及Web瀏覽器。CGI程序一般完成Web網(wǎng)頁(yè)中表單(Form)數(shù)據(jù)的處理、數(shù)據(jù)庫(kù)查詢和實(shí)現(xiàn)與傳統(tǒng)應(yīng)用系統(tǒng)的集成等工作。CGI程序可以用任何程序設(shè)計(jì)語(yǔ)言編寫,如Shell腳本語(yǔ)言、Perl、Fortran、Pascal、C語(yǔ)言等。但是用C語(yǔ)言編寫的CGI程序具有執(zhí)行速度快、安全性高(因?yàn)镃語(yǔ)言程序是編譯執(zhí)行且不可被修改)等特點(diǎn)。

  CGI接口標(biāo)準(zhǔn)包括標(biāo)準(zhǔn)輸入、環(huán)境變量、標(biāo)準(zhǔn)輸出三部分。

  1.標(biāo)準(zhǔn)輸入

  CGI程序像其他可執(zhí)行程序一樣,可通過(guò)標(biāo)準(zhǔn)輸入(stdin)從Web服務(wù)器得到輸入信息,如Form中的數(shù)據(jù),這就是所謂的向CGI程序傳遞數(shù)據(jù)的POST方法。這意味著在操作系統(tǒng)命令行狀態(tài)可執(zhí)行CGI程序,對(duì)CGI程序進(jìn)行調(diào)試。POST方法是常用的方法,本文將以此方法為例,分析CGI程序設(shè)計(jì)的方法、過(guò)程和技巧。

  2.環(huán)境變量

  操作系統(tǒng)提供了許多環(huán)境變量,它們定義了程序的執(zhí)行環(huán)境,應(yīng)用程序可以存取它們。Web服務(wù)器和CGI接口又另外設(shè)置了自己的一些環(huán)境變量,用來(lái)向CGI程序傳遞一些重要的參數(shù)。CGI的GET方法還通過(guò) 環(huán)境變量QUERY-STRING向CGI程序傳遞Form中的數(shù)據(jù)。

  3.標(biāo)準(zhǔn)輸出

  CGI程序通過(guò)標(biāo)準(zhǔn)輸出(stdout)將輸出信息傳送給Web服務(wù)器。傳送給Web服務(wù)器的信息可以用各種格式,通常是以純文本或者HTML文本的形式,這樣我們就可以在命令行狀態(tài)調(diào)試CGI程序,并且得到它們的輸出。

  下面是一個(gè)簡(jiǎn)單的CGI程序,它將HTML中Form的信息直接輸出到We b瀏覽器。
  #include
  #include
  main()
  {
   int,i,n;
  printf (″Contenttype:text/plain\n\n″);
  n=0;
  if(getenv(″CONTENT-LENGTH″))
  n=atoi(getenv(CONTENT-LENGTH″));
  for (i=0;i< n;i++)>br>   putchar(getchar());
  putchar (′\n′);
  fflush(stdout);
  }


  下面對(duì)此程序作一下簡(jiǎn)要的分析。

  prinft (″Contenttype:text/plain\n\n″);
  此行通過(guò)標(biāo)準(zhǔn)輸出將字符串″Contenttype:text/plain\n\n″傳送給Web服務(wù)器。它是一個(gè)MIME頭信息,它告訴Web服務(wù)器隨后的輸出是以純ASCII文本的形式。請(qǐng)注意在這個(gè)頭信息中有兩個(gè)新行符,這是因?yàn)閃eb服務(wù)器需要在實(shí)際的文本信息開始之前先看見(jiàn)一個(gè)空行。

  if (getenv(″CONTENT-LENGTH″))
  n=atoi (getenv(″CONTENT-LENGTH″));
  此行首先檢查環(huán)境變量CONTENT-LENGTH是否存在。Web服務(wù)器在調(diào)用使用POST方法的CGI程序時(shí)設(shè)置此環(huán)境變量,它的文本值表示W(wǎng)eb服務(wù)器傳送給CGI程序的輸入中的字符數(shù)目,因此我們使用函數(shù)atoi() 將此環(huán)境變量的值轉(zhuǎn)換成整數(shù),并賦給變量n。請(qǐng)注意Web服務(wù)器并不以文件結(jié)束符來(lái)終止它的輸出,所以如果不檢查環(huán)境變量CONTENT-LENGTH,CGI程序就無(wú)法知道什么時(shí)候輸入結(jié)束了。


  for (i=0;i< n;i++)>br>   putchar(getchar());
  此行從0循環(huán)到(CONTENT-LENGTH-1)次將標(biāo)準(zhǔn)輸入中讀到的每一個(gè)字符直接拷貝到標(biāo)準(zhǔn)輸出,也就是將所有的輸入以ASCII的形式回送給Web服務(wù)器。

  通過(guò)此例,我們可將CGI程序的一般工作過(guò)程總結(jié)為如下幾點(diǎn)。
  1.通過(guò)檢查環(huán)境變量CONTENT-LENGTH,確定有多少輸入;
  2.循環(huán)使用getchar()或者其他文件讀函數(shù)得到所有的輸入;
  3.以相應(yīng)的方法處理輸入;
  4.通過(guò)″Contenttype:″頭信息,將輸出信息的格式告訴Web服務(wù)器;
  5.通過(guò)使用printf()或者putchar()或者其他的文件寫函數(shù),將輸出傳送給Web服務(wù)器。
  總之,CGI程序的主要任務(wù)就是從Web服務(wù)器得到輸入信息,進(jìn)行處理,然后將輸出結(jié)果再送回給Web服務(wù)器。


二、環(huán)境變量

  環(huán)境變量是文本串(名字/值對(duì)),可以被OS Shell或其他程序設(shè)置 ,也可以被其他程序訪問(wèn)。它們是Web服務(wù)器傳遞數(shù)據(jù)給CGI程序的簡(jiǎn)單手段,之所以稱為環(huán)境變量是因?yàn)樗鼈兪侨肿兞?任何程序都可以存取它們。

  下面是CGI程序設(shè)計(jì)中常常要用到的一些環(huán)境變量。
  HTTP-REFERER:調(diào)用該CGI程序的網(wǎng)頁(yè)的URL。
  REMOTE-HOST:調(diào)用該CGI程序的Web瀏覽器的機(jī)器名和域名。
  REQUEST-METHOD:指的是當(dāng)Web服務(wù)器傳遞數(shù)據(jù)給CGI程序時(shí)所采用的方法,分為GET和POST兩種方法。GET方法僅通過(guò)環(huán)境變量(如QUERY-STRING)傳遞數(shù)據(jù)給CGI程序,而POST方法通過(guò)環(huán)境變量和標(biāo)準(zhǔn)輸入傳遞數(shù)據(jù)給CGI程序,因此POST方法可較方便地傳遞較多的數(shù)據(jù)給CGI程序。

  SCRIPT-NAME:該CGI程序的名稱。
  QUERY-STRING:當(dāng)使用POST方法時(shí),Form中的數(shù)據(jù)最后放在QUERY-STRING中,傳遞給CGI程序。
  CONTENT-TYPE:傳遞給CGI程序數(shù)據(jù)的MIME類型,通常為″applica tion/x-www-form-url encodede″,它是從HTML Form中以POST方法傳遞數(shù)據(jù)給CGI程序的數(shù)據(jù)編碼類型,稱為URL編碼類型。
  CONTENT-LENGTH:傳遞給CGI程序的數(shù)據(jù)字符數(shù)(字節(jié)數(shù))。
  在C語(yǔ)言程序中,要訪向環(huán)境變量,可使用getenv()庫(kù)函數(shù)。例如:
  if (getenv (″CONTENT-LENGTH″))
   n=atoi(getenv (″CONTENT-LENGTH″));
  請(qǐng)注意程序中最好調(diào)用兩次getenv():第一次檢查是否存在該環(huán)境變量,第二次再使用該環(huán)境變量。這是因?yàn)楹瘮?shù)getenv()在給定的環(huán)境變量名不存在時(shí),返回一個(gè)NULL(空)指針,如果你不首先檢查而直接引用它,當(dāng)該環(huán)境變量不存在時(shí)會(huì)引起CGI程序崩潰。


三、From輸入的分析和解碼

  1.分析名字/值對(duì)

  當(dāng)用戶提交一個(gè)HTML Form時(shí),Web瀏覽器首先對(duì)Form中的數(shù)據(jù)以名字/值對(duì)的形式進(jìn)行編碼,并發(fā)送給Web服務(wù)器,然后由Web服務(wù)器傳遞給CGI程序。其格式如下:
  name1=value1&name2=value2&name3=value3&name4=value4&...
  其中名字是Form中定義的INPUT、SELECT或TEXTAREA等標(biāo)置(Tag)名字,值是用戶輸入或選擇的標(biāo)置值。這種格式即為URL編碼,程序中需要對(duì)其進(jìn)行分析和解碼。要分析這種數(shù)據(jù)流,CGI程序必須首先將數(shù)據(jù)流分解成一組組的名字/值對(duì)。這可以通過(guò)在輸入流中查找下面的兩個(gè)字符來(lái)完成。
  每當(dāng)找到字符=,標(biāo)志著一個(gè)Form變量名字的結(jié)束;每當(dāng)找到字符& ,標(biāo)志著一個(gè)Form變量值的結(jié)束。請(qǐng)注意輸入數(shù)據(jù)的最后一個(gè)變量的值不以&結(jié)束。
  一旦名字/值對(duì)分解后,還必須將輸入中的一些特殊字符轉(zhuǎn)換成相應(yīng)的ASCII字符。這些特殊字符是:
  +:將+轉(zhuǎn)換成空格符;
  %xx:用其十六進(jìn)制ASCII碼值表示的特殊字符。根據(jù)值xx將其轉(zhuǎn)換成相應(yīng)的ASCII字符。
  對(duì)Form變量名和變量值都要進(jìn)行這種轉(zhuǎn)換。下面是一個(gè)對(duì)Form數(shù)據(jù)進(jìn)行分析并將結(jié)果回送給Web服務(wù)器的CGI程序。


  #include
  #include
  #include
  int htoi(char *);
  main()
  {
   int i,n;
  char c;
  printf (″Contenttype: text/plain\n\n″);
  n=0;
  if (getenv(″CONTENT-LENGTH″))
   n=atoi(getenv(″CONTENT-LENGTH″));
  for (i=0; i< n;i++){>br>    int is-eq=0;
  c=getchar();
  switch (c){
   case ′&′:
    c=′\n′;
    break;
   case ′+′:
    c=′ ′;
    break;
   case ′%′:{
    char s[3];
    s[0]=getchar();
    s[1]=getchar();
    s[2]=0;
    c=htoi(s);
    i+=2;
   }
   break;
  case ′=′:
   c=′:′;
   is-eq=1;
   break;
  };
  putchar(c);
  if (is-eq) putchar(′ ′);
  }
  putchar (′\n′);
  fflush(stdout);
  }
  /* convert hex string to int */
  int htoi(char *s)
  {
   char *digits=″0123456789ABCDEF″;
  if (islower (s[0])) s[0]=toupper(s[0]);
  if (islower (s[1])) s[1]=toupper(s[1]);
  return 16 * (strchr(digits, s[0]) -strchr (digits,′0′)
)
  +(strchr(digits,s[1])-strchr(digits,′0′));
  }

  上面的程序首先輸出一個(gè)MIME頭信息給Web服務(wù)器,檢查輸入中的字符數(shù),并循環(huán)檢查每一個(gè)字符。當(dāng)發(fā)現(xiàn)字符為&時(shí),意味著一個(gè)名字/值對(duì)的結(jié)束,程序輸出一個(gè)空行;當(dāng)發(fā)現(xiàn)字符為+時(shí),將它轉(zhuǎn)換成空格; 當(dāng)發(fā)現(xiàn)字符為%時(shí),意味著一個(gè)兩字符的十六進(jìn)制值的開始,調(diào)用htoi()函數(shù)將隨后的兩個(gè)字符轉(zhuǎn)換為相應(yīng)的ASCII字符;當(dāng)發(fā)現(xiàn)字符為=時(shí),意味著一個(gè)名字/值對(duì)的名字部分的結(jié)束,并將它轉(zhuǎn)換成字符:。最后將轉(zhuǎn)換后的字符輸出給Web服務(wù)器。



四、產(chǎn)生HTML輸出

  CGI程序產(chǎn)生的輸出由兩部分組成:MIME頭信息和實(shí)際的信息。兩部分之間以一個(gè)空行分開。我們已經(jīng)看到怎樣使用MIME頭信息″Cont enttype:text/plain\n\n″和printf()、put char()等函數(shù)調(diào)用來(lái)輸 出純ASCII文本給Web服務(wù)器。實(shí)際上,我們也可以使用MIME頭信息″C ontenttype:text/html\n\n″來(lái)輸出HTML源代碼給Web服務(wù)器。請(qǐng)注意任何MIME頭信息后必須有一個(gè)空行。一旦發(fā)送這個(gè)MIME頭信息給We b服務(wù)器后,Web瀏覽器將認(rèn)為隨后的文本輸出為HTML源代碼,在HTML源代碼中可以使用任何HTML結(jié)構(gòu),如超鏈、圖像、Form,及對(duì)其他CGI程 序的調(diào)用。也就是說(shuō),我們可以在CGI程序中動(dòng)態(tài)產(chǎn)生HTML源代碼輸出 ,下面是一個(gè)簡(jiǎn)單的例子。

  #include
  #include
  main()
  {
]]>
Java與Flash誰(shuí)才是網(wǎng)頁(yè)游戲領(lǐng)導(dǎo)者http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2403&Page=1wangxinxin2010-12-10 11:13:30
  Flash

  事實(shí)上,F(xiàn)lash中的游戲開發(fā)已經(jīng)進(jìn)行了多年的嘗試。但至今為止仍然停留在中、小型游戲的開發(fā)上。游戲開發(fā)的很大一部份都受限于它的CPU 能力和大量代碼的管理。不過(guò)可喜的是,F(xiàn)lash Player 7運(yùn)行時(shí)性能提高了2至5倍;而且最新的Flash MX 2004 Professional 提供了項(xiàng)目管理和代碼維護(hù)方面的功能, Actionscript 2.0 的發(fā)布也使得程序更加容易維護(hù)和開發(fā)。

  實(shí)很難界定Web 應(yīng)用服務(wù)的范圍究竟有多大,它似乎它擁有無(wú)限的可能。隨著網(wǎng)絡(luò)的逐漸滲透,基于客戶端- 服務(wù)器的應(yīng)用設(shè)計(jì)也開始逐漸受到歡迎,并且一度被譽(yù)為最具前景的方式。但是,這種方式開發(fā)者可能要花更多的時(shí)間在服務(wù)器后臺(tái)處理能力和架構(gòu)上,并且將它們與前臺(tái)(Flash端)保持同步。

  目前國(guó)內(nèi)就有一款完全基于 Flash 制作的網(wǎng)頁(yè)游戲《黑暗契約》。此款游戲遲遲不得開放,原因如何?團(tuán)隊(duì)有關(guān)人員如是說(shuō):

  “Flash 游戲中會(huì)不會(huì)卡的問(wèn)題,絕大部分都是由于 Flash 的天生缺陷造成的,例如單線程、內(nèi)存管理等等…另外,在服務(wù)端我們也做了大量?jī)?yōu)化,把所有主要的內(nèi)容都緩沖在了內(nèi)存中,保證在大量并發(fā)時(shí)的通信和響應(yīng)。此外,為了保證服務(wù)器出現(xiàn)異常狀況時(shí)玩家信息不至于丟失,我們又為內(nèi)存緩沖開發(fā)了復(fù)雜的管理和寫回機(jī)制。黑暗契約服務(wù)器的投入成本會(huì)是以往游戲的3倍!

基于 Flash 制作的網(wǎng)頁(yè)游戲《黑暗契約》

 ]]>
C語(yǔ)言之父Dennis Ritchiehttp://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2402&Page=1wangxinxin2010-12-10 11:11:34

丹尼斯·麥卡利斯泰爾·里奇(Dennis MacAlistair Ritchie,1941年9月9日生),出生于美國(guó)紐約布朗克斯維爾(Bronxville)。著名的美國(guó)計(jì)算機(jī)科學(xué)家,對(duì)C語(yǔ)言和其他編程語(yǔ)言、Multics和Unix等操作系統(tǒng)的發(fā)展做出了巨大貢獻(xiàn)。

里奇在哈佛大學(xué)學(xué)習(xí)物理學(xué)和應(yīng)用數(shù)學(xué)畢業(yè),1967年他進(jìn)入貝爾實(shí)驗(yàn)室,主管貝爾實(shí)驗(yàn)室位于新澤西州的計(jì)算機(jī)科學(xué)研究中心的系統(tǒng)軟件研究部門,目前他是朗訊技術(shù)公司系統(tǒng)軟件研究部門的領(lǐng)導(dǎo)人。1983年他與肯·湯普遜一起獲得了圖靈獎(jiǎng)。理由是他們“研究發(fā)展了通用的操作系統(tǒng)理論,尤其是實(shí)現(xiàn)了UNIX操作系統(tǒng)”。1999年兩人為發(fā)展C語(yǔ)言和Unix操作系統(tǒng)一起獲得了美國(guó)國(guó)家技術(shù)獎(jiǎng)?wù)隆?/p>

當(dāng)有人問(wèn)里奇為什么使用他使用的方式開發(fā)了C語(yǔ)言的時(shí)候,里奇回答說(shuō)“這樣做看上去很好”,他說(shuō)任何人在同一地方、同一時(shí)間會(huì)像他那樣做的。但是其他許多人認(rèn)為這只不過(guò)反映出了里奇的謙虛。C++的開發(fā)者和設(shè)計(jì)師、里奇在貝爾實(shí)驗(yàn)室的同事比雅尼·斯特勞斯特魯普說(shuō):“假如里奇決定在那十年里將他的精力花費(fèi)在稀奇古怪的數(shù)學(xué)上,那么Unix將胎死腹中。”

肯·湯普遜(左)和丹尼斯·里奇(右)

肯·湯普遜(左)和丹尼斯·里奇(右)

事實(shí)上,丹尼斯·里奇與肯·湯普遜兩人發(fā)展了C語(yǔ)言,同時(shí)發(fā)展了Unix操作系統(tǒng),在電腦工業(yè)史上占有重要的席位。至今為止C語(yǔ)言在發(fā)展軟件和操作系統(tǒng)時(shí)依然是一個(gè)非常常用的電腦語(yǔ)言,它對(duì)許多現(xiàn)代的編程語(yǔ)言如C++、C#、Objective-C、Java和JavaScript擁有極大的影響。在操作系統(tǒng)方面Unix也具有極大的影響:今天市場(chǎng)上有許多不同的Unix方言如AIX、Solaris、Mac OS X和BSD等,以及與Unix非常相似的系統(tǒng)如Minix和非常普及的Linux操作系統(tǒng)。甚至其Microsoft Windows操作系統(tǒng)與Unix相競(jìng)爭(zhēng)的微軟為他們的用戶和開發(fā)者提供了與Unix相容的工具和C語(yǔ)言編譯器。

里奇還參加發(fā)展了Unix和C語(yǔ)言的兩個(gè)后繼軟件:Plan 9和Inferno操作系統(tǒng)以及Limbo語(yǔ)言。兩者均是基于他以前的工作上發(fā)展的。

在技術(shù)討論中,他常被稱為dmr,這是他在貝爾實(shí)驗(yàn)室的Email地址。值得注意的是,雖然丹尼斯·里奇是C語(yǔ)言的作者,他本人最喜歡的程序語(yǔ)言卻是Alef。

Dennis MacAlistair=

Dennis MacAlistair Ritchie

]]>
C語(yǔ)言難點(diǎn)分析http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2401&Page=1wangxinxin2010-12-10 11:10:48
了解了基本的變量類型后,我們要進(jìn)一步了解它的存儲(chǔ)類別和變量作用域問(wèn)題。

變量類別 子類別
局部變量 靜態(tài)變量(離開函數(shù),變量值仍保留)
自動(dòng)變量
寄存器變量
全局變量 靜態(tài)變量(只能在本文件中用)
非靜態(tài)變量(允許其他文件使用)

換一個(gè)角度

變量類別 子類別
靜態(tài)存儲(chǔ)變量 靜態(tài)局部變量(函數(shù))
靜態(tài)全局變量(本文件)
非靜態(tài)全局/外部變量(其他文件引用)
動(dòng)態(tài)存儲(chǔ)變量 自動(dòng)變量
寄存器變量
形式參數(shù)

extern型的存儲(chǔ)變量在處理多文件問(wèn)題時(shí)常能用到,在一個(gè)文件中定義 extern型的變量即說(shuō)明這個(gè)變量用的是其他文件的。順便說(shuō)一下,筆者在做課設(shè)時(shí)遇到out of memory的錯(cuò)誤,于是改成做多文件,再把它include進(jìn)來(lái)(注意自己寫的*.h要用“”不用<>),能起到一定的效用。static 型的在讀程序?qū)懡Y(jié)果的試題中是個(gè)考點(diǎn)。多數(shù)時(shí)候整個(gè)程序會(huì)出現(xiàn)多個(gè)定義的變量在不同的函數(shù)中,考查在不同位置同一變量的值是多少。主要是遵循一個(gè)原則,只要本函數(shù)內(nèi)沒(méi)有定義的變量就用全局變量(而不是main里的),全局變量和局部變量重名時(shí)局部變量起作用,當(dāng)然還要注意靜態(tài)與自動(dòng)變量的區(qū)別。

函數(shù):

對(duì)于函數(shù)最基本的理解是從那個(gè)叫main的單詞開始的,一開始總會(huì)覺(jué)得把語(yǔ)句一并寫在main里不是挺好的么,為什么偏擇出去。其實(shí)這是因?yàn)閷?duì)函數(shù)還不夠熟練,否則函數(shù)的運(yùn)用會(huì)給我們編程帶來(lái)極大的便利。我們要知道函數(shù)的返回值類型,參數(shù)的類型,以及調(diào)用函數(shù)時(shí)的形式。事先的函數(shù)說(shuō)明也能起到一個(gè)提醒的好作用。所謂形參和實(shí)參,即在調(diào)用函數(shù)時(shí)寫在括號(hào)里的就是實(shí)參,函數(shù)本身用的就是形參,在畫流程圖時(shí)用平行四邊形表示傳參。

函數(shù)的另一個(gè)應(yīng)用例子就是遞歸了,筆者開始比較頭疼的問(wèn)題,反應(yīng)總是比較遲鈍,按照老師的方法,把遞歸的過(guò)程耐心準(zhǔn)確的逐級(jí)畫出來(lái),學(xué)習(xí)的效果還是比較好的,會(huì)覺(jué)得這種遞歸的運(yùn)用是挺巧的,事實(shí)上,著名的八皇后、漢諾塔等問(wèn)題都用到了遞歸。

例子:
 



數(shù)組:

分為一維數(shù)組和多維數(shù)組,其存儲(chǔ)方式畫為表格的話就會(huì)一目了然,其實(shí)就是把相同類型的變量有序的放在一起。因此,在處理比較多的數(shù)據(jù)時(shí)(這也是大多數(shù)的情況)數(shù)組的應(yīng)用范圍是非常廣的。

具體的實(shí)際應(yīng)用不便舉例,而且絕大多數(shù)是與指針相結(jié)合的,筆者個(gè)人認(rèn)為學(xué)習(xí)數(shù)組在更大程度上是為學(xué)習(xí)指針做一個(gè)鋪墊。作為基礎(chǔ)的基礎(chǔ)要明白幾種基本操作:即數(shù)組賦值、打印、排序(冒泡排序法和選擇排序法)、查找。這些都不可避免的用到循環(huán),如果覺(jué)得反應(yīng)不過(guò)來(lái),可以先一點(diǎn)點(diǎn)的把循環(huán)展開,就會(huì)越來(lái)越熟悉,以后自己編寫一個(gè)功能的時(shí)候就會(huì)先找出內(nèi)在規(guī)律,較好的運(yùn)用了。另外數(shù)組做參數(shù)時(shí),一維的[]里可以是空的,二維的第一個(gè)[]里可以是空的但是第二個(gè)[]中必須規(guī)定大小。
冒泡法排序函數(shù): 
void bubble( int a[] , int n) 

    
int i,j,k; 
    
for (i=1,i<n;i++
    
for (j=0;j< n-i-1; j++
    
if (a[j]>a[j+1]) 
    { 
        k
=a[j]; 
        a[j]
=a[j+1]; 
        a[j
+1]=k; 
    } 

選擇法排序函數(shù):
void sort( int a[] , int n) 
...
    
int i,j,k,t; 
    
for (i=0,i< n-1 ;i++
    
...
        k
=i ; 
        
for ( j=i+1 ;j<n;j++
            
if (a[k]<a[j]) k=j ; 
        
if ( k!=i ) 
        
...
            t
=a[i]; 
            a[i]
=a[k]; 
            a[k]
=t; 
        }
 
    }
 
}
 

]]>
ELF 程序開發(fā)教程及技術(shù)討論專貼http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2400&Page=1wangxinxin2010-12-10 11:07:00西門子x65/x75上的 ELF 程序大家已經(jīng)見(jiàn)識(shí)過(guò)了,你有沒(méi)想過(guò)寫出自己的 ELF 程序呢?如果你有C語(yǔ)言基礎(chǔ),那么加入 ELF 程序開發(fā)的隊(duì)伍吧。
要在西門子x65/x75上使用 ELF 程序,你應(yīng)該確定自己的機(jī)器上正確的刷了適合你機(jī)型的3個(gè)補(bǔ)丁(如下):
function library
elfloader
swi-hook
查看機(jī)型在待機(jī)下輸入 *#06# 選更多,sW-Version一行就是了
現(xiàn)在的 ELF 程序一般是被刷過(guò)以上3個(gè)補(bǔ)丁的正確版本的機(jī)器所通用的(也有可能會(huì)限制機(jī)型,看程序怎么寫的了8-) )
下面進(jìn)入正題

目錄:
1.IAR SI 安裝
2.在手機(jī)上運(yùn)行 ELF 程序

3.如何用 IAR 編寫 ELF
4.例1:內(nèi)存和文件的操作
5.例2:屏幕輸出和鍵盤控制
6.例3:一個(gè)后臺(tái)計(jì)時(shí)的小程序
7.例4:內(nèi)存駐留程序
8.FAQ


1.IAR SI 安裝
www.iar.com下載 IAR Embedded Workbench  For ARM 的30天試用版,最新版為4.41好象(>100 mb),程序下載是免費(fèi)的,但是會(huì)要你先注冊(cè)。填寫正確的油箱以后,就會(huì)把使用序列號(hào)發(fā)給你。安裝沒(méi)說(shuō)的了吧,一路下一步,下一步,等等。

2.在手機(jī)上運(yùn)行 ELF 程序
論壇上很多說(shuō)明了,再扯就遠(yuǎn)了點(diǎn):-')

3.如何用 IAR 編寫 ELF
開始一個(gè) ELF 程序的編寫,還是比較簡(jiǎn)單 :P
在菜單上選擇 “Project->Create New Project”
然后選添加"Project->Add Files"把你用其他IDE寫好的C程序添加進(jìn)來(lái)就可以了
工程必須還要有 func.asm (入口點(diǎn)) 和 div.r79 (這個(gè)好象莫必要?我也不太清楚,我是業(yè)余的:( )
C程序知道怎么寫,問(wèn)題就不大。
你可能會(huì)問(wèn),怎么使用到手機(jī)里面那些需要的功能函數(shù)呢?這就需要 swilib.h 這個(gè)頭文件了(附件提供),這里面定義了n多函數(shù),大家看名字猜吧。。。因?yàn)闆](méi)說(shuō)明,滅辦法,唉。
上面的操作做好以后,就可以編譯我們的程序了,在 IAR 環(huán)境里左邊的 Workspace 下面,把 Debug 選成 Release,然后在工程上點(diǎn)右鍵,選屬性 CPU 可以不用改,下面的 Processor mode 改為 Arm,在 Library Configuration 標(biāo)簽里,把 Library 選成 None,就可以編譯了。這里你也可以在 Linker 里面設(shè)置相關(guān)連接選項(xiàng)。生成完畢后,你就可以在 你的工程\Release\Exe 目錄里找到生成的 ELF 文件,放到手機(jī)里看看呢?:P

4.例1:內(nèi)存和文件的操作
創(chuàng)建 main.c 如下后添加到你的工程里:
//main.c
#include "swilib.h"
void ElfKiller(void) { //用于 elf 退出時(shí)的相關(guān)操作
    extern void *ELF_BEGIN;
    //這里一般使用 mfree(), freeWS() 來(lái)釋放內(nèi)存
    ((void (*)(void *))(mfree_adr()))(ELF_BEGIN); // 懶得解釋 :(
}
int main(char *exename, char *fname) { //主函數(shù)
//參數(shù) exename 表示被動(dòng)使用的ELF? 格式 4:\Zbin\xyz.elf
//參數(shù) fname 傳遞文件名, 格式 0:\Misc\data.txt
//如果 ELF 啟動(dòng)自身則為 0
    char *mem;
    int i, err;
    int handle;
    if (fname) {
        //操作標(biāo)準(zhǔn)文件:
        handle = fopen(fname, A_ReadWrite+A_BIN+A_Append+A_Create, P_READ+P_WRITE, err);
        //表示按記錄文件打開,數(shù)據(jù)添加到文件末尾,如果文件不存在則創(chuàng)建之
        //如果為 handle=fopen (fname,A_ReadOnly+A_BIN, 0,err);
        //則表示按只讀方式打開文件,具體常數(shù)參看 swilib.h
        if (handle != -1) { //-1 = error
            mem = malloc(10000); //分配內(nèi)存: AllocWS() 按行分配 (2b)
            if (mem != 0) { //0 = error
                i = fread(handle, mem, 10000, err); //返回讀取得字節(jié)數(shù),如果錯(cuò)誤返回 error。
                //放置你的代碼在這里 makesomebody (mem,i);
                fwrite(handle, mem, i, err);
                mfree(mem); //釋放內(nèi)存: FreeWS() 按行釋放
            }
            fclose(handle); //關(guān)閉文件
        }
    }
    SUBPROC((void *)ElfKiller); //放這個(gè)東西在這里就最好了,不存在也沒(méi)關(guān)系!
    return(0);
}
//PS. 由于 x65 中文件的讀取和記錄是按 32767 字節(jié)的塊操作的,
//因此將 fread() 和 fwrite() 改造為 fread32 () 和 fwrite32()
int fread32(int fh, char *buf, int len, unsigned int *err) { // (c) Rst7
    int clen;
    int rlen;
    int total=0;
    while (len) {
        if (len > 16384) clen = 16384; else clen = len;
        total += (rlen = fread(fh, buf, clen, err));
        if (rlen != clen) break;
        buf += rlen;
        len -= clen;
    }
    return(total);
}

最后不要忘了還有 func.asm 這個(gè)文件:
;Func.asm
    PUBLIC ELF_BEGIN
    RSEG ELFBEGIN:DATA
ELF_BEGIN
defadr MACRO a,b
   PUBLIC a
a EQU b
   ENDM
   END

5.例2:屏幕輸出和鍵盤控制
通過(guò)導(dǎo)航鍵控制屏幕上的符號(hào)移動(dòng),長(zhǎng)按紅鍵退出。本例子基于 TED- A (c) Of rst7
看本例時(shí)最好從下往上看:)

創(chuàng)建 main.c 如下后添加到你的工程里:
//main.c
//屏幕和鍵盤處理
#include "swilib.h"
typedef struct {
    GUI gui;
    //WSHDR *ws1;
    //WSHDR *ws2;
    //int i1;
} MAIN_GUI;
typedef struct {
    CSM_RAM csm;
    int gui_id;
} MAIN_CSM;
const int minus11 = -11;
const unsigned int INK = 0;
const unsigned int PAPER = 1;
volatile int xx = 0, yy = 0; //繪圖坐標(biāo)
const char bmp[12] = {0xFC, 0x86, 0xB3, 0xA9, 0xB1, 0xA9, 0x81, 0xFF, 0, 0, 0, 0};
const IMGHDR img = {8, 12, 0x1, 0, (char *)bmp};
//============
//屏幕輸出
//============
void DrwImg(IMGHDR *img, int x, int y, int *pen, int *brush)  {
    RECT rc;
    DRWOBJ drwobj;
    StoreXYWHtoRECT(rc, x, y, img->w, img->h);
    SetPropTo_Obj5(drwobj, &rc, 0, img);
    SetColor(drwobj, pen, brush);
    DrawObject(drwobj);
}
void DrawScreen(void) {
    int *ink = GetPaletteAdrByColorIndex(INK);
    int *paper = GetPaletteAdrByColorIndex(PAPER);
    int x = xx;
    DrwImg((IMGHDR *)img, x, yy, ink, paper);
}
//繪制屏幕
void method0(MAIN_GUI *data) {
    DrawScreen();
}
void method1(MAIN_GUI *data, void *(*malloc_adr)(int)) {}
void method2(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
void method3(MAIN_GUI *data, void *(*malloc_adr)(int), void (*mfree_adr)(void *)) {}
void method4(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
void method7(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
int method8(void) {return(0);}
int method9(void) {return(0);}
//============
//按鍵控制
//============
int method5 (MAIN_GUI *data, GUI_MSG *msg) {
    //if (msg->gbsmsg->msg==KEY_UP) //釋放按鍵時(shí)
    if ((msg->gbsmsg->msg == KEY_DOWN) || (msg->gbsmsg->msg == LONG_PRESS)) //按下鍵或者長(zhǎng)按鍵時(shí)
        switch(msg->gbsmsg->submess) {
        case RED_BUTTON:
            return(1); //發(fā)生 generalFunc 流調(diào)用 GUI - > 關(guān)閉 GUI
        case UP_BUTTON:
            if (yy > 0) --yy; break;
        case LEFT_BUTTON:
            if (xx > 0) --xx; break;
        case DOWN_BUTTON:
            if (yy < 130) ++yy; break;
        case RIGHT_BUTTON:
            if ( xx < 120) ++xx; break;
        //case GREEN_BUTTON:
        //case RIGHT_SOFT:
        //case ENTER_BUTTON:
        //case LEFT_SOFT:
        //case VOL_UP_BUTTON:
        //case VOL_DOWN_BUTTON:
        //case '0':
        //case '9':
        //case '#':
        //SUBPROC((void *)DoDiskAccess,1);
        //降低其他處理的優(yōu)先級(jí)以繪制窗口
        }
    DrawScreen();
    return(0);
}
const void *const gui_methods[11] = {
    (void *)method0, //Redraw
    (void *)method1, //Create
    (void *)method2, //Close
    (void *)method3, //Focus
    (void *)method4, //Unfocus
    (void *)method5, //OnKey
    0,
    (void *)method7, //Destroy
    (void *)method8,
    (void *)method9,
    0
};
const RECT Canvas={0,0,131,175};
void maincsm_oncreate(CSM_RAM *data) {
    MAIN_GUI *main_gui = malloc(sizeof (MAIN_GUI));
    MAIN_CSM *csm = (MAIN_CSM *)data;
    zeromem(main_gui, sizeof (MAIN_GUI));
    //ustk=malloc(STKSZ); //為程序分配內(nèi)存
    //info_ws=AllocWS(512);
    main_gui->gui.canvas = (void *)(Canvas);
    main_gui->gui.flag30 = 2;
    main_gui->gui.methods = (void *)gui_methods; //基本方法(見(jiàn)上面)
    main_gui->gui.item_ll.data_mfree = (void (*)(void *))mfree_adr(); //我也不清楚:(
    csm->csm.state = 0;
    csm->csm.unk1 = 0;
    csm->gui_id = CreateGUI(main_gui); //直接創(chuàng)建 GUI
}
void Killer(void) { //退出程序
    extern void *ELF_BEGIN;
    //mfree(ustk); //釋放內(nèi)存
    //FreeWS(info_ws);
    ((void (*)(void *))(mfree_adr()))(ELF_BEGIN);
}
void maincsm_onclose(CSM_RAM *csm) {
    //GBS_StopTimer(light_tmr);
    SUBPROC((void *)Killer);
}
int maincsm_onmessage(CSM_RAM *data, GBS_MSG *msg) {
    return(1);
}
unsigned short maincsm_name_body[140];
const struct {
    CSM_DESC maincsm;
    WSHDR maincsm_name;
} MAINCSM = {
                {
                    maincsm_onmessage, //信息進(jìn)程
                    maincsm_oncreate, //創(chuàng)建時(shí)調(diào)用的方法
                    //如果機(jī)型為 S75 移除以下4行
                    //并在 swilib.h 里取消對(duì) #define NEWSGOLD 這行的注釋
                    //0,
                    //0,
                    //0,
                    //0,
                    maincsm_onclose, //關(guān)閉時(shí)調(diào)用的方法
                    sizeof (MAIN_CSM),
                    1,
                    minus11
                },
                {
                    maincsm_name_body,
                    NAMECSM_MAGIC1,
                    NAMECSM_MAGIC2,
                    0x0,
                    139
                }
            };
int main(char *exename, char *fname) {
    char dummy[sizeof (MAIN_CSM)];
    //strcpy(filename,fname); //保存數(shù)據(jù)到文件
    CreateCSM(MAINCSM.maincsm, dummy, 0);
    return 0;
}
]]>
Java替代C語(yǔ)言的可能性http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2399&Page=1wangxinxin2010-12-10 11:02:54

前不久CSDN刊登了一篇《C語(yǔ)言已經(jīng)死了》的文章,引起了一些爭(zhēng)論。其實(shí)那篇文章是從Ed Burnette的博客上轉(zhuǎn)載來(lái)的,原文題目是“Die, C, die!”,直譯過(guò)來(lái)應(yīng)該是《去死吧,C!》,表達(dá)的是一種詛咒,而不是判斷。翻譯稱《C語(yǔ)言已經(jīng)死了》,顯然是一種煽風(fēng)點(diǎn)火的誤讀。CSDN網(wǎng)友對(duì)于其觀點(diǎn)已經(jīng)進(jìn)行了批判,不過(guò)坦率地說(shuō),由于這些批判基于一個(gè)扭曲的翻譯文本,所以不但沒(méi)有什么新鮮的地方,而且也沒(méi)有抓住原作者的重點(diǎn)。

    實(shí)際情況是這樣的,最近一段時(shí)間,在國(guó)外的技術(shù)社群里刮起了一股風(fēng),不少人在討論Java做為C語(yǔ)言替代者而成為最主流的基礎(chǔ)軟件編程語(yǔ)言的可能性。從大部分人發(fā)表的觀點(diǎn)來(lái)看,對(duì)于Java替代C的趨勢(shì)還是支持的。

     基礎(chǔ)軟件是指這樣一類軟件,其主要任務(wù)是把計(jì)算機(jī)的潛能充分發(fā)揮出來(lái),面向上層應(yīng)用軟件提供一個(gè)高效、可靠的功能集。這些軟件會(huì)被密集地調(diào)用,性能上的一點(diǎn)點(diǎn)滯后都會(huì)在實(shí)踐中被成百上千倍的放大。所以對(duì)于基礎(chǔ)軟件來(lái)說(shuō),性能至少與可靠性一樣重要。我們?cè)谝恍┗A(chǔ)軟件的源代碼里,常?吹揭恍┏舐脑O(shè)計(jì),看到一些變態(tài)的黑客技巧,在其他的領(lǐng)域里,這是不被鼓勵(lì)的,但是在基礎(chǔ)軟件中,這就是合理的,可以接受的。

     C語(yǔ)言目前仍在一些領(lǐng)域里堅(jiān)挺,在操作系統(tǒng)、虛擬機(jī)和設(shè)備驅(qū)動(dòng)程序開發(fā)方面,它可能是永遠(yuǎn)的王者。但是在其他的基礎(chǔ)軟件領(lǐng)域,比如數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)服務(wù)器、圖形圖像處理等,C語(yǔ)言繼續(xù)占據(jù)霸主地位的原因其實(shí)只有兩個(gè),一是快,二是熟悉的人多,而且經(jīng)驗(yàn)豐富。

    但是這兩點(diǎn)現(xiàn)在都遭到了挑戰(zhàn)。

    首先是速度。Java的執(zhí)行速度在JDK1.4的時(shí)候達(dá)到了這樣一個(gè)水平,就是對(duì)于一個(gè)一般水平的開發(fā)者來(lái)說(shuō),他寫的C++程序已經(jīng)不再比對(duì)等的Java程序跑得更快了。隨后的JDK 5.0和6.0進(jìn)一步提高了執(zhí)行性能,由不同的組織舉行的多項(xiàng)評(píng)測(cè)結(jié)果表明,Java與C語(yǔ)言的整體執(zhí)行效率差距在一倍以內(nèi),也就是說(shuō),素以速度著稱、并且為了速度放棄了很多東西的C語(yǔ)言,現(xiàn)在比裝備齊全的Java只快不到一倍了。這還不算,如果考慮到新的計(jì)算環(huán)境,C語(yǔ)言的速度優(yōu)勢(shì)有可能僅僅是一個(gè)錯(cuò)覺(jué)。因?yàn),世界上只有很少的人有能力在多CPU計(jì)算平臺(tái)上用C語(yǔ)言寫出又快又正確的大程序,在這些人中間,又只有很少很少的人有能力用C語(yǔ)言寫出一個(gè)在大型的、異構(gòu)的網(wǎng)絡(luò)環(huán)境下能夠充分發(fā)揮各節(jié)點(diǎn)計(jì)算能力的大規(guī)模并行程序。也就是說(shuō),你也許有能力把程序效能提高一倍,從而充分發(fā)揮一臺(tái)價(jià)值6000元人民幣的PC的計(jì)算潛力,為客戶節(jié)省1000元錢。但如果是在一個(gè)由1000臺(tái)機(jī)器組成的大型異構(gòu)網(wǎng)絡(luò)并行計(jì)算的環(huán)境下,你寫的C程序恐怕性能還會(huì)遠(yuǎn)遠(yuǎn)低于對(duì)應(yīng)的Java程序,更不要說(shuō)巨大的后期維護(hù)成本,而由此帶來(lái)的損失可能是1000萬(wàn)或者更多。

    其次是經(jīng)驗(yàn)。很多人都宣稱自己的C功力如何如何了得,但是實(shí)際上,即使是真正的C高手也不得不花相當(dāng)可觀的時(shí)間來(lái)尋找并且調(diào)試錯(cuò)誤,尤其是內(nèi)存方面的錯(cuò)誤。大部分用C寫的上規(guī)模的軟件都存在一些內(nèi)存方面的錯(cuò)誤,需要花費(fèi)大量的精力和時(shí)間把產(chǎn)品穩(wěn)定下來(lái)。這還沒(méi)有把安全方面的缺陷考慮在內(nèi),現(xiàn)在大部分的開發(fā)者在代碼安全方面的知識(shí)都很薄弱,安全漏洞在代碼中相當(dāng)普遍,而在C語(yǔ)言中,這一不足暴露得格外明顯。最大的挑戰(zhàn)或許得說(shuō)是并發(fā)問(wèn)題了,并發(fā)是一個(gè)很復(fù)雜的問(wèn)題,需要在相當(dāng)高的抽象層面上解決,而C語(yǔ)言的抽象機(jī)制過(guò)于簡(jiǎn)單,提供不了高層的抽象,因此在開發(fā)者只能從一些“并發(fā)原語(yǔ)”出發(fā)去構(gòu)造并發(fā)程序,這跟用鉛筆刀鋸大樹沒(méi)什么分別,直截了當(dāng)?shù)卣f(shuō),大部分C程序員根本沒(méi)有能力編寫高效無(wú)缺陷的并發(fā)程序。

    所以殘酷的事實(shí)是,當(dāng)一個(gè)人說(shuō)自己的C語(yǔ)言如何了得,經(jīng)驗(yàn)如何豐富時(shí),非?赡芩f(shuō)的是,自己在用C語(yǔ)言寫單機(jī)、單線程的,不會(huì)遭到外界攻擊的,在時(shí)間預(yù)算上沒(méi)有什么壓力,而且用戶能夠忍受一個(gè)很長(zhǎng)的產(chǎn)品穩(wěn)定期的應(yīng)用程序方面非常有經(jīng)驗(yàn)。遺憾的是,市場(chǎng)環(huán)境和計(jì)算環(huán)境已經(jīng)完全變化。面對(duì)更復(fù)雜的計(jì)算環(huán)境,用C語(yǔ)言來(lái)編寫高質(zhì)量的大規(guī)模軟件,是只有真正的專家團(tuán)隊(duì)才能完成的工作。如果你曾經(jīng)有過(guò)連續(xù)數(shù)日苦苦追蹤和調(diào)試一個(gè)內(nèi)存泄露、或者線程錯(cuò)誤的經(jīng)歷,你就會(huì)明白,你可能不是這樣的專家。

    相比之下,Java在抽象機(jī)制、基礎(chǔ)設(shè)施、安全和并發(fā)方面,與C語(yǔ)言比起來(lái),就好像是馬克沁重機(jī)槍對(duì)弓箭。比如并發(fā),Java 5.0加入的java.util.concurrent包,可能是目前主流語(yǔ)言中對(duì)于并發(fā)問(wèn)題最強(qiáng)有力的支持庫(kù)。Java的內(nèi)存管理和安全機(jī)制,也已經(jīng)被實(shí)踐證明確實(shí)能夠有效地減少程序的缺陷。這也就是那篇詛咒文章的原文的意圖。

    所以,我的態(tài)度明確的,我認(rèn)為Java替代C是一個(gè)進(jìn)步的想法,不過(guò)世界上進(jìn)步的想法很多,能夠美夢(mèng)成真的卻寥寥無(wú)幾。Java是否真的能夠在基礎(chǔ)軟件領(lǐng)域強(qiáng)有力地替代C語(yǔ)言呢?我看至少短期內(nèi)還做不到,原因如下:

1. 人的問(wèn)題。能夠用C語(yǔ)言寫出優(yōu)秀基礎(chǔ)軟件的人固然不多,能用Java寫出來(lái)的人恐怕更少。Java有好幾百萬(wàn)開發(fā)者,但是他們?cè)诟墒裁?大部分是去搞企業(yè)級(jí)開發(fā)、Web開發(fā)了,有多少人真的理解Java的內(nèi)存模型?有多少人能夠熟練使用concurrent包中提供的那些工具?很多使用Java多年的人沒(méi)有寫過(guò)socket程序,不了解Java多線程的開銷,不清楚如何進(jìn)行性能診斷和調(diào)優(yōu),而這些在寫基礎(chǔ)軟件的時(shí)候是必備的技能。大部分Java程序員在剛剛學(xué)會(huì)Java之后就轉(zhuǎn)向Web開發(fā),把主要精力花費(fèi)在掌握一個(gè)又一個(gè)大型的、復(fù)雜的、具有厚厚的抽象層和華麗結(jié)構(gòu)的frameworks上,不但對(duì)真實(shí)計(jì)算機(jī)體系結(jié)構(gòu)不清楚,對(duì)于Java虛擬出來(lái)的那個(gè)計(jì)算環(huán)境也不清楚。因此,要把Java社群編程轉(zhuǎn)變成能夠擔(dān)負(fù)起下一代基礎(chǔ)軟件開發(fā)工作的尖兵,不但難度很大,而且必須花費(fèi)足夠的時(shí)間。

2. Java的內(nèi)存消耗太大。對(duì)于系統(tǒng)級(jí)程序來(lái)說(shuō),內(nèi)存消耗大,就意味著cache命中率降低,與磁盤交換數(shù)據(jù)的可能性增大,對(duì)性能的影響還是比較嚴(yán)重的。現(xiàn)在很多人還是覺(jué)得Java慢,主要的原因已經(jīng)不是Java跑得慢,而是由于內(nèi)存消耗過(guò)大導(dǎo)致的綜合性能下降。這個(gè)問(wèn)題不解決,Java就只能用來(lái)做一些比較上層的基礎(chǔ)軟件。也許隨著計(jì)算機(jī)硬件的發(fā)展,這個(gè)問(wèn)題會(huì)逐步得到解決?

3. 風(fēng)格的問(wèn)題。這個(gè)問(wèn)題我認(rèn)為是最嚴(yán)重的。基礎(chǔ)軟件開發(fā)崇尚的是自由、直接、透明、簡(jiǎn)單、高效,要像匕首一樣鋒利,像戰(zhàn)士一樣勇猛,像農(nóng)夫一樣樸實(shí),反對(duì)繁瑣華麗的設(shè)計(jì),反對(duì)架床迭屋的層層抽象,反對(duì)復(fù)雜的結(jié)構(gòu)和不必要的靈活性。而Java社群多年來(lái)形成的設(shè)計(jì)風(fēng)格與此格格不入,甚至可以說(shuō)是對(duì)立的。Java在意識(shí)形態(tài)上是要面向企業(yè)應(yīng)用軟件的開發(fā),所以特別強(qiáng)調(diào)架構(gòu),強(qiáng)調(diào)設(shè)計(jì)模式,強(qiáng)調(diào)標(biāo)準(zhǔn),強(qiáng)調(diào)規(guī)規(guī)矩矩,強(qiáng)調(diào)高姿態(tài),強(qiáng)調(diào)一種華貴的宮廷氣質(zhì)。在C中,你吃飯就是吃飯,捧起碗來(lái)喝酒,放下筷子罵娘,甩開膀子抓肉,擼起袖子抹油。而在Java中,你經(jīng)常為了要干某件事,先new一個(gè)對(duì)象,然后以這個(gè)對(duì)象為參數(shù)new另一個(gè)對(duì)象,如此這般重復(fù)n遍,得到真正需要的對(duì)象,最后就是為了調(diào)用那個(gè)對(duì)象的一個(gè)方法,就好比吃飯時(shí)焚香洗面,漱口凈手,戰(zhàn)戰(zhàn)兢兢,畢恭畢敬。在C中,遇到問(wèn)題要像亡命徒,像流氓版程咬金,管你三七二十一,沖上去就是三板斧,還怕劈不死你丫的。在Java里,遇到問(wèn)題要像宋襄公,要張榜檄文,要名正言順,要禮儀之邦,要把架子拉開了,把譜兒擺足了。Java的口號(hào)是,不管劈不劈的死,先把你小子感動(dòng)了再說(shuō)。 這套繁瑣的東西,對(duì)于基礎(chǔ)軟件開發(fā)來(lái)說(shuō),既不必要,也很難習(xí)慣。需要說(shuō)明的是,這不是Java語(yǔ)言的問(wèn)題,其實(shí)Java本身不必如此復(fù)雜、如此巴洛克。從語(yǔ)言本身來(lái)看,Java也可以是輕快直接的,也可是酣暢淋漓的。只不過(guò)十多年來(lái)幾乎沒(méi)有人這樣用過(guò),所以大家已經(jīng)不知道:如果不來(lái)個(gè)一步三叩首,那么該怎么用Java寫程序?

    正是因?yàn)樯厦娴倪@種種原因(可能還不全面),直到最近,第一流的基礎(chǔ)軟件幾乎都還是C語(yǔ)言編寫的,或者至少其核心部分還是以C為主。而且我認(rèn)為,在短期內(nèi),這種局面不會(huì)有大的改變。當(dāng)然,如果Java社群能夠克服上面的這些問(wèn)題,充分發(fā)揮出Java本身的優(yōu)勢(shì),在基礎(chǔ)領(lǐng)域開發(fā)出一大批一流的支撐軟件,那么局面是可以改變的,而且這種改變也是進(jìn)步的,值得歡迎的

]]>
一個(gè)簡(jiǎn)單的一箭穿心程序http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2398&Page=1wangxinxin2010-12-10 10:29:29#include<graphics.h>
#include<math.h>  
#define FNX(x1) (int)(x (x1)*sl)
#define FNY(y1) (int)(MAXY-(y (y1)*sl))
#define R(theta) 1-pow(cos(1*theta),1)  
int sl=50,MAXY;
float x1,y1,xs,ys,r,theta;
/*畫心*/
void draw(int x,int y)
{
for(theta=0;theta<2*3.14;theta =0.01)
{r=R(theta);
  x1=r*sin(theta);y1=r*cos(theta);
  xs=FNX(x1);ys=FNY(y1);
  if(theta==0)moveto(xs,ys);else lineto(xs,ys);
}
}  
/*畫箭頭*/
void jian()
{
line(205,235,200,240);
line(200,240,205,245);
line(200,240,214,240);
line(400,240,500,240);
line(485,235,480,240);
line(480,240,485,245);
line(490,235,485,240);
line(485,240,490,245);
line(495,235,490,240);
line(490,240,495,245);
line(500,235,495,240);
line(495,240,500,245);
line(505,235,500,240);
line(500,240,505,245);
line(485,235,505,235);
line(485,245,505,245);
}
/*主程序*/
main()
{int driver=DETECT,mode;
initgraph(&driver,&mode,"");
setbkcolor(1);
setcolor(4);
MAXY=getmaxy();
draw(280,280);/*左心*/
draw(370,280);/*右心*/
jian();
  getch();
closegraph();
}


看到大家討論對(duì)編程好不關(guān)系的話題,真的感到失望,如果你不是來(lái)學(xué)習(xí)的,請(qǐng)不要回復(fù)本貼,但也看到大家對(duì)于一些人生攻擊的醒悟,
象 Momoass 能用公平的態(tài)度來(lái)對(duì)待大家的發(fā)言.
    converse (創(chuàng)系) 也來(lái)勸大家說(shuō)話和氣.
   相信他們這樣的人才有成功的品質(zhì),非常熱情,做事情就需要這樣的人.
]]>
C語(yǔ)言中有幾個(gè)不懂http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2397&Page=1wangxinxin2010-12-10 10:27:23[討論]C語(yǔ)言中有幾個(gè)不懂
議題作者:爆米花
信息來(lái)源:邪惡八進(jìn)制信息安全團(tuán)隊(duì)(www.eviloctal.com

本人絕對(duì)不是灌水的垃圾貼,本人初學(xué)C語(yǔ)言 其中之不懂地方很多,對(duì)于邪八這里,高手如云,我就怕發(fā)的貼被當(dāng)作廢貼,其實(shí)其他論壇我也可以去發(fā),但是給我發(fā)回復(fù)層次不齊,惟獨(dú)邪八回復(fù)的 技術(shù)含量頗高,所以硬頭皮來(lái)發(fā)貼,本人第一次發(fā)貼,我要把該講的講清楚,請(qǐng)大師記住我的名字,這樣以后我發(fā)的我覺(jué)得難的問(wèn)題的帖子就不會(huì)被當(dāng)廢貼了,好謝謝不講了我發(fā)以下內(nèi)容求高手回復(fù)
    編寫一個(gè)C程序,輸入a,b,c 3個(gè)值,輸出其中最大者
        #include<stdio.h>
       void main()
       {int a,b,c,max;     ←我能理解的是 int(機(jī)器語(yǔ)言) a b c 哪個(gè)最大
        printf("please input a,b,c:\n");    ←printf(機(jī)器語(yǔ)言) 請(qǐng)輸入a b c 回車
        scanf("%d,%d,%d,&a,&b,&c");    ←scanf(機(jī)器語(yǔ)言)  后面的%d,%d,%d,&a,&b,&c 到底表達(dá)個(gè)什么意思我就不知道了
        max=a;    ←從這后面我就不知道 講的是什么意思了 怎么能夠理解呢
        if(max<b)    ←如果a<b a=b
           max=b;
        if(max<c)     ←如果a<c a=c
           max=c;
        printf("the largest number is %d",max);    最大的數(shù)是%d ?????不懂 誰(shuí)能幫我解釋一下啊 這是C語(yǔ)言第2頁(yè)的內(nèi)容        我就這個(gè)樣子 怎么辦!!!!!!!!!
       }
]]>
如何學(xué)習(xí)C語(yǔ)言的指針http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2396&Page=1wangxinxin2010-12-10 10:15:37  (*ptr)++;
  ptr++; } 這個(gè)例子將整型數(shù)組中各個(gè)單元的值加1。由于每次循環(huán)都將指針ptr加1,所以每次循環(huán)都能訪問(wèn)數(shù)組的下一個(gè)單元。再看例子: 例四: 1、chara[20]; 2、int*ptr=a;   ...
  ... 3、ptr+=5; 在這個(gè)例子中,ptr被加上了5,編譯器是這樣處理的:將指針ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的單位是字節(jié),故現(xiàn)在的ptr所指向的地址比起加5后的ptr所指向的地址來(lái)說(shuō),向高地址方向移動(dòng)了20個(gè)字節(jié)。在這個(gè)例子中,沒(méi)加5前的ptr指向數(shù)組a的第0號(hào)單元開始的四個(gè)字節(jié),加5后,ptr已經(jīng)指向了數(shù)組a的合法范圍之外了。雖然這種情況在應(yīng)用上會(huì)出問(wèn)題,但在語(yǔ)法上卻是可以的。這也體現(xiàn)出了指針的靈活性。 如果上例中,ptr是被減去5,那么處理過(guò)程大同小異,只不過(guò)ptr的值是被減去5乘sizeof(int),新的ptr指向的地址將比原來(lái)的ptr所指向的地址向低地址方向移動(dòng)了20個(gè)字節(jié)。 總結(jié)一下,一個(gè)指針ptrold加上一個(gè)整數(shù)n后,結(jié)果是一個(gè)新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值增加了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié)。就是說(shuō),ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向高地址方向移動(dòng)了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié)。 一個(gè)指針ptrold減去一個(gè)整數(shù)n后,結(jié)果是一個(gè)新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值減少了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié),就是說(shuō),ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向低地址方向移動(dòng)了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié) 運(yùn)算符&和* 這里&是取地址運(yùn)算符,*是...書上叫做"間接運(yùn)算符"。 &a的運(yùn)算結(jié)果是一個(gè)指針,指針的類型是a的類型加個(gè)*,指針?biāo)赶虻念愋褪莂的類型,指針?biāo)赶虻牡刂仿铮蔷褪莂的地址。 *p的運(yùn)算結(jié)果就五花八門了?傊*p的結(jié)果是p所指向的東西,這個(gè)東西有這些特點(diǎn):它的類型是p指向的類型,它所占用的地址是p所指向的地址。例五: inta=12; intb; int*p; int**ptr; p=&a; //&a的結(jié)果是一個(gè)指針,類型是int*,指向的類型是int,指向的地址是a的地址。 *p=24; //*p的結(jié)果,在這里它的類型是int,它所占用的地址是p所指向的地址,顯然,*p就是變量a。 ptr=&p; //&p的結(jié)果是個(gè)指針,該指針的類型是p的類型加個(gè)*,在這里是int **。該指針?biāo)赶虻念愋褪莗的類型,這里是int*。該指針?biāo)赶虻牡刂肪褪侵羔榩自己的地址。 *ptr=&b; //*ptr是個(gè)指針,&b的結(jié)果也是個(gè)指針,且這兩個(gè)指針的類型和所指向的類型是一樣的,所以用&b來(lái)給*ptr賦值就是毫無(wú)問(wèn)題的了。 **ptr=34; //*ptr的結(jié)果是ptr所指向的東西,在這里是一個(gè)指針,對(duì)這個(gè)指針再做一次*運(yùn)算,結(jié)果就是一個(gè)int類型的變量。 指針表達(dá)式 一個(gè)表達(dá)式的最后結(jié)果如果是一個(gè)指針,那么這個(gè)表達(dá)式就叫指針表式。下面是一些指針表達(dá)式的例子: 例六: inta,b; intarray[10]; int*pa; pa=&a; //&a是一個(gè)指針表達(dá)式。 int**ptr=&pa; //&pa也是一個(gè)指針表達(dá)式。 *ptr=&b; //*ptr和&b都是指針表達(dá)式。 ]]>
單片機(jī)的C語(yǔ)言中數(shù)組的用法http://www.hufushizhe.com/bbs/dispbbs.asp?BoardID=62&ID=2395&Page=1wangxinxin2010-12-10 10:12:35

數(shù)組是由具有相同類型的數(shù)據(jù)元素組成的有序集合。數(shù)組是由數(shù)組名來(lái)表示的,數(shù)組中的數(shù)據(jù)由特定的下標(biāo)來(lái)唯一確定。引入數(shù)組的目的,是使用一塊連續(xù)的內(nèi)存空間存儲(chǔ)多個(gè)類型相同的數(shù)據(jù),以解決一批相關(guān)數(shù)據(jù)的存儲(chǔ)問(wèn)題。數(shù)組與普通變量一樣,也必須先定義,后使用。數(shù)組在C51語(yǔ)言的地位舉足輕重,因此深入地了解數(shù)組是很有必要的。下面就對(duì)數(shù)組進(jìn)行詳細(xì)的介紹。

1)一維數(shù)組

一維數(shù)組是最簡(jiǎn)單的數(shù)組,用來(lái)存放類型相同的數(shù)據(jù)。數(shù)據(jù)的存放是線性連續(xù)的。

用以下例程說(shuō)明數(shù)組的建立、數(shù)據(jù)操作:

[size=#]#include



[size=#]unsigned char array[10];//定義一個(gè)有10個(gè)單元的數(shù)組


[size=#]void main()

[size=#]{

[size=#]unsigned char i;

[size=#]for(i=0;i<10;i++)

[size=#]{

[size=#]array=i; //用下標(biāo)調(diào)用數(shù)組中的元素

[size=#]}


[size=#]while(1);

[size=#]}

數(shù)組名是用來(lái)表示數(shù)組的標(biāo)識(shí),其實(shí)它是數(shù)組的首地址,即一個(gè)指針。不過(guò)它所表示的地址是固定的,不能改動(dòng)。如前幾章所述的相關(guān)內(nèi)容,array[2]*(array+2)是等效的,不過(guò)不能用array++,因?yàn)?font face="Times new=" Roman? New?>array是常量。

上面[size=#]的程序中的數(shù)組是靜態(tài)建立的,以下例程來(lái)用說(shuō)明數(shù)組的動(dòng)態(tài)建立。

[size=#]#include

[size=#]#include




[size=#]unsigned char *parray;


[size=#]void main()

[size=#]{

[size=#]unsigned char i;

[size=#]parray=(unsigned char *)malloc(10); //動(dòng)態(tài)創(chuàng)建一個(gè)數(shù)組

[size=#]for(i=0;i<10;i++)

[size=#]{

[size=#]parray=i; //向數(shù)組中賦值

[size=#]}

[size=#]free(parray); //釋放數(shù)組

[size=#]while(1);

[size=#]}

[size=#]字符串是數(shù)組的一個(gè)重要特例。它的每個(gè)單元的數(shù)據(jù)均為字符類型(char),最后一個(gè)單元為'\0'0x00[size=#]),用來(lái)表示字符串的結(jié)束。C51函數(shù)庫(kù)中提供了專門對(duì)字符串進(jìn)行處理的函數(shù),用以下例程說(shuō)明:

[size=#]#include

[size=#]#include




[size=#]char s[]={'y','a','h','o','o','\0'};

[size=#]//定義一個(gè)字符串,并對(duì)它進(jìn)行初始化,以'\0'結(jié)束


[size=#]void main()

[size=#]{

[size=#]char s_temp[10];

[size=#]strcpy(s_temp,s);//strcpy位于string.h頭文件中,實(shí)現(xiàn)字符拷貝

[size=#]//s為一個(gè)常量,不能s++

[size=#]strcpy(s_temp,"yahoo");//與上面的語(yǔ)句等效

[size=#]while(1);

[size=#]}

[size=#]以下列出幾種字符串的靈活用法,希望能夠幫助讀者深入了解字符串:

[size=#]#include

[size=#]#include





[size=#]char *get_sub_string(char *s,unsigned char n)

[size=#]{

[size=#]int i;int d=0;int fore=0;

[size=#]int len=strlen(s);

[size=#]for(i=0;i< FONT>

[size=#]{

[size=#]if(s==',')

[size=#]{

[size=#]s='\0';

[size=#]d++;

[size=#]if(d==n)

[size=#]{

[size=#]return s+fore;

[size=#]}

[size=#]else

[size=#]{

[size=#]fore=i+1;

[size=#]}

[size=#]}

[size=#]}

[size=#]return NULL;

[size=#]}


[size=#]void main()

[size=#]{

[size=#]unsigned char c;

[size=#]char string[20];

[size=#]c="yahoo"[2]; //c='h'


[size=#]strcpy(string,"123,234,345,456");

[size=#]strcpy(string,get_sub_string(string,2));

[size=#]while(1);

[size=#]}

[size=#](2)二維數(shù)組

[size=#]可由兩個(gè)下標(biāo)確定元素的數(shù)組就稱為二維數(shù)組。其定義的一般形式為:

類型說(shuō)明符 數(shù)組名[常量表達(dá)式1][常量表達(dá)式2]

例如:int array[6][4];

定義了一個(gè)二維數(shù)組array,有64列,共24個(gè)元素。

兩個(gè)方括號(hào)中的常量表達(dá)1與常量表達(dá)式2規(guī)定了數(shù)組的行數(shù)與列數(shù),從而確定了數(shù)組中的元素個(gè)數(shù)。行下標(biāo)從0開始,最大為5,6;列下標(biāo)也從0開始,最大為3,共4列。數(shù)組中共有6X4=24個(gè)元素,具體如下表示:

array[0][0]
array[0][1]
array[0][2]
array[0][3]
array[1][0]
array[1][1]
array[1][2]
array[1][3]
array[2][0]
array[2][1]
array[2][2]
array[2][3]
array[3][0]
array[3][1]
array[3][2]
array[3][3]
array[4][0]
array[4][1]
array[4][2]
array[4][3]
array[5][0]
array[5][1]
array[5][2]
array[5][3]

實(shí)際使用時(shí),可以把上述二維數(shù)組看作一個(gè)64列的矩陣,是一個(gè)平面的二維結(jié)構(gòu)。那么編譯程序是如何用一[size=#]維的存儲(chǔ)空間給這樣一個(gè)二維結(jié)構(gòu)分配連續(xù)的存儲(chǔ)單元的呢[size=#]C51采用按行存放的方法,即在內(nèi)存中先存放第0行元素,再存放第1行、第2行、......元素,每行中先存放第0列,接著存放第1列、第2列、......的元素。

[size=#]#include

[siz=#]#include




[size=#]void main()

[size=#]{

]]>
国产剧情视频在线观看-国产剧情麻豆女教师在线观看-国产剧情精品在线观看-国产剧情精品-国产剧情91-国产玖玖在线观看
<dfn id="is4kg"></dfn>
  • <ul id="is4kg"></ul>
  • <abbr id="is4kg"></abbr>
  • <ul id="is4kg"></ul>
    <bdo id="is4kg"></bdo>
    国产嫩草一区二区三区在线观看| 伊人天天久久大香线蕉av色| y111111国产精品久久婷婷| 成人深夜直播免费观看| 视频在线一区二区三区| 5278欧美一区二区三区| 亚洲**2019国产| 久久久久成人网| 欧美精品亚洲精品| 久久国产精品-国产精品| 午夜精品在线视频| 日韩国产高清一区| 97香蕉超级碰碰久久免费软件| 亚洲在线观看一区| 91po在线观看91精品国产性色 | 91亚洲精品久久久久久久久久久久| …久久精品99久久香蕉国产| 久久综合色一本| 国产成人av在线播放| 日韩美女激情视频| 国产精品成人v| 欧美亚洲另类在线一区二区三区 | 91精品久久久久久久久久久久久久| 欧美男人的天堂| 57pao成人永久免费视频| 懂色av一区二区三区在线播放| 欧美国产日韩免费| 99热在线播放| 国产91精品久久久久| 91在线国产电影| 国产精品扒开腿爽爽爽视频| 国产精品爽黄69| 免费在线观看一区二区| 国产精品久久久久久av| 亚洲va韩国va欧美va精四季| 91精品视频观看| 奇米888一区二区三区| 久久免费视频网| 日韩高清国产一区在线观看| 国产日韩欧美电影在线观看| 欧美一区二区.| 成人国产亚洲精品a区天堂华泰| 黑人另类av| 91sao在线观看国产| 精品免费视频123区| 国产91成人在在线播放| 日产中文字幕在线精品一区| 国产精品极品尤物在线观看| 91av在线看| 亚洲欧美日韩国产yyy| 国产高清自拍一区| 国产美女精品免费电影| 7777免费精品视频| 色综合久综合久久综合久鬼88| 久久99精品久久久久久水蜜桃| 91精品国产综合久久香蕉最新版| 欧美大片免费观看| 粉嫩av免费一区二区三区| 97精品一区二区三区| 国产成人精品在线视频| 极品日韩久久| 国产精品久久精品国产| 青青久久av北条麻妃黑人| 国产在线久久久| 国产精品v片在线观看不卡| 韩日午夜在线资源一区二区 | 国产亚洲精品美女久久久m| 色一情一乱一伦一区二区三区丨 | 蜜桃视频在线观看91| 国产精品高清网站| 欧洲日本亚洲国产区| 欧美激情国产日韩精品一区18| 久久精品国产99精品国产亚洲性色| 91久久精品国产| 国产91在线播放| 热re99久久精品国产66热| 一区二区不卡在线观看| 久久日韩精品| 国产精品裸体一区二区三区| 99超碰麻豆| 91久久国产综合久久蜜月精品| 国产综合在线观看视频| 成人精品久久久| 91久久国产精品| 亚洲qvod图片区电影| 成人av在线亚洲| 91免费观看| 欧美激情小视频| 狠狠干一区二区| 国产免费观看久久黄| 国产a∨精品一区二区三区不卡| 成人免费网站在线观看| 国产日韩在线精品av| 国产成人综合精品| 国产精品第二页| 欧美亚洲第一页| 91精品国产91久久久久久久久| 午夜美女久久久久爽久久| 97在线视频免费看| 欧洲亚洲免费视频| 国产精品自拍偷拍| 亚洲图色在线| 成人动漫网站在线观看| 3d精品h动漫啪啪一区二区| 亚洲综合小说区| 国产精品中出一区二区三区| 欧美日韩在线精品一区二区三区| 国产精品日韩一区二区三区| 国产伦精品一区二区三区免费视频| 国产精品免费一区二区三区| 精品国产一区二区三| 99视频国产精品免费观看| 97人人爽人人喊人人模波多| 成人在线中文字幕| 国产精品视频福利| 日本福利一区二区三区| 在线观看日韩片| 欧美在线激情网| 国产精品三级网站| 99re视频在线| 成人自拍偷拍| 亚洲精品日韩成人| 农村寡妇一区二区三区| 欧美精品成人在线| 81精品国产乱码久久久久久| 精品欧美日韩| 国产精品视频免费一区| 精品国产一区二区三区免费| 欧美在线播放一区| 亚洲午夜精品一区二区三区| 欧美激情精品久久久久久| 91av国产在线| 91久久在线视频| 超碰97网站| 日韩成人在线资源| 97香蕉久久夜色精品国产| 国产精品一区二区性色av| 国产精品手机在线| 欧美高清视频在线观看| 国产精品久久久久秋霞鲁丝| 99精品在线直播| 天天爽天天狠久久久| 青青草一区二区| 日本一区二区不卡高清更新| 国产精品一区二区久久久久| 中文字幕久久综合| 亚洲欧美久久久久一区二区三区| 国产+成+人+亚洲欧洲| 国产成人短视频| 人人做人人澡人人爽欧美| 天天综合色天天综合色hd| 国色天香2019中文字幕在线观看| 国产精品综合不卡av| 精品午夜一区二区三区| 国自在线精品视频| 不卡一卡2卡3卡4卡精品在| 一区二区三区的久久的视频| 国产精品久久久久久久电影| 免费亚洲一区二区| 国产成人中文字幕| 欧美午夜免费| 日本久久久久久久久久久| 国产精品加勒比| 国产做受69高潮| 91九色极品视频| 欧美黑人视频一区| 91中文字精品一区二区| 中文字幕中文字幕99| 91嫩草在线视频| 一区二区免费电影| 69堂成人精品视频免费| 久久久久久18| 国产综合 伊人色| 国产成人中文字幕| 亚洲一区美女| ts人妖另类在线| 88xx成人精品| 欧美极品日韩| 91精品久久久久久久久久入口 | 91精品国产综合久久久久久蜜臀| 亚洲精品美女久久7777777| 成人黄色免费片| 欧美肥老妇视频| 国产精品视频入口| 国产精品va在线播放| 三级三级久久三级久久18| 国产在线拍偷自揄拍精品| 中文字幕中文字幕99| 国产精品美女黄网| 国产乱人伦真实精品视频| 欧美多人爱爱视频网站| 国产精品一区二区三区不卡| 国产精品99蜜臀久久不卡二区| 日韩精品欧美在线| av电影成人| 国产成人精品一区二区| 亚洲激情一区二区三区| 成人欧美一区二区三区黑人免费| 日本精品久久中文字幕佐佐木| 日本成人三级电影网站| yellow视频在线观看一区二区| 欧美一级视频免费在线观看| 亚洲欧美日韩国产yyy| 国产精品久久精品国产| 国产人妖伪娘一区91| 欧美激情精品久久久久久变态| 国产成人一区二区三区免费看| 国产精品午夜视频| 欧美亚洲一区在线| 日韩精品电影网站| 国产欧美亚洲日本| 国产日韩在线看片| 日本一区二区三区四区视频| 五月天色一区| 精品综合在线| 91在线看网站| 国产综合久久久久| 国产福利成人在线| 亚洲91av视频| 欧美大片欧美激情性色a∨久久| 蜜桃av色综合| 成人午夜影院在线观看| 成人www视频在线观看| 欧美一区在线直播| 国模精品系列视频| 综合色婷婷一区二区亚洲欧美国产| 蜜桃精品久久久久久久免费影院| 国产精品一区二区三区精品| 91传媒视频在线观看| 国产精品偷伦视频免费观看国产| 午夜精品理论片| 伊甸园精品99久久久久久| 日韩av不卡在线播放| 精品无码久久久久久久动漫| 成人看片视频| 99中文视频在线| 亚洲xxxxx性| 国产女人18毛片水18精品| 日本一区视频在线播放| 欧美日韩在线一区二区三区| 欧美极品jizzhd欧美| 麻豆成人在线播放| 欧美在线播放一区二区| 日韩av一区二区三区美女毛片| 玖玖玖精品中文字幕| 精品一区二区视频| 免费精品视频一区二区三区| 久久婷婷开心| 欧美国产二区| 视频一区免费观看| 亚洲国产精品一区在线观看不卡| 日韩中文一区| 一区二区三区四区欧美| 欧美丰满老妇厨房牲生活| 欧美激情图片区| 8090成年在线看片午夜| 日产日韩在线亚洲欧美| 国产精品视频免费观看www| 国产有码一区二区| 97免费资源站| 激情伦成人综合小说| 久久人人爽爽人人爽人人片av| 欧美精品一区二区三区久久| 日韩成人av网站| 中文字幕日韩一区二区三区 | 欧洲亚洲一区二区三区四区五区| 日韩欧美三级一区二区| 中国人体摄影一区二区三区| 午夜欧美不卡精品aaaaa| 日韩影片在线播放| 国产欧美va欧美va香蕉在| 在线观看亚洲视频啊啊啊啊| 国产精品福利观看| 欧美高跟鞋交xxxxhd| 欧美激情乱人伦一区| 欧美精品aaa| 啪一啪鲁一鲁2019在线视频| 日本久久中文字幕| 国产精品一区二区三区久久 | 97精品国产97久久久久久免费| 91国自产精品中文字幕亚洲| 国产精品国产三级国产aⅴ浪潮| 国产乱肥老妇国产一区二| 成人中文字幕在线观看| 国产伦精品一区二区三区照片| 欧美一区二区三区在线免费观看| 一区二区三区精品国产| 国产不卡在线观看| 99久久久精品免费观看国产| 欧美精品免费观看二区| 欧美激情亚洲精品| 国产精品视频大全| 国产成人亚洲欧美| 亚洲精品国产一区| 国产成人亚洲综合91| 懂色中文一区二区三区在线视频| 日本在线观看不卡| 97超碰国产精品女人人人爽| 成人国内精品久久久久一区| 精品久久sese| 中国成人在线视频| 国产精品99久久久久久www| 51精品国产人成在线观看| 欧美亚洲精品日韩| 成人性生交大片免费观看嘿嘿视频 | 中文字幕免费在线不卡| 国产成人高潮免费观看精品| 国产成人av一区二区三区| 四虎永久国产精品| 国产福利成人在线| 久久久久久久久一区| 91精品国产91久久久久久久久| 亚洲最大av网| 欧美福利视频在线| 亚洲a在线播放| 亚洲成人av动漫| 国产精品色午夜在线观看| 免费亚洲一区二区| 2019中文字幕在线观看| av一区二区在线看| 欧美激情亚洲激情| 99在线免费观看视频| 欧美黑人狂野猛交老妇| 97久久天天综合色天天综合色hd| 色综合久久悠悠| 亚洲自拍偷拍第一页| 一区二区日本伦理| 91pron在线| 午夜精品久久久久久久99黑人 | 久久久久这里只有精品| 成人精品一区二区三区| 性欧美精品一区二区三区在线播放| 国产精品女主播| 日韩福利视频| 91免费视频网站| 欧美激情一级精品国产| 成人一区二区在线| 欧洲亚洲在线视频| 色狠狠久久av五月综合| 成人免费xxxxx在线观看| 在线观看欧美一区| 国产日韩三区| 国产精品久久久久久久美男| 日产精品一线二线三线芒果| 91久久久在线| 2025国产精品视频| 久久精品久久精品国产大片| 国产精品国产亚洲伊人久久| 亚洲 国产 日韩 综合一区| 97久久天天综合色天天综合色hd| 高清一区二区三区日本久| 久久综合精品一区| 国产在线a不卡| 97精品一区二区三区| 欧美日韩在线精品| 亚洲一区精品电影| 久久久久日韩精品久久久男男| 成人av片网址| 国产精品wwww| 欧美极品少妇与黑人| 国产伦精品一区二区三区四区免费 | 国产欧美日韩视频一区二区三区| 欧美综合在线第二页| 日韩精品无码一区二区三区| 国产精品白丝jk白祙| 国产精品你懂得| 51色欧美片视频在线观看| 日本在线免费观看一区| 国产激情一区二区三区在线观看 | 国产精品无码专区在线观看| 久久久久亚洲精品国产| 日韩高清专区| 精品国产一区二区三区日日嗨| 成人精品aaaa网站| 国产精品福利片| 久久久噜噜噜久久| 国产在线精品自拍| 青青草原成人在线视频| 视频在线精品一区| 久久久久久艹| 亚洲一区二区三区毛片| 99国产视频在线| 免费av在线一区二区| 成人黄色大片在线免费观看| 91精品国产自产91精品| 玛丽玛丽电影原版免费观看1977| 国产日本欧美视频| 欧美孕妇孕交黑巨大网站| 亚洲激情图片| 久久大片网站| 国产精品美女免费看| 国产精品jizz视频| 成人综合网网址| 日韩av电影在线网| 9.1国产丝袜在线观看| 久久久久久久影院| 一区二区三区四区不卡| 亚洲国产精品毛片| 四虎一区二区| 亚洲v欧美v另类v综合v日韩v| 欧美日韩综合网| 美女黄毛**国产精品啪啪| 国产一区二区无遮挡| 91国产在线免费观看| 成人伊人精品色xxxx视频| 国产精品你懂得| 国产精品十八以下禁看| 国产精品久久久久影院日本| 国产精品久久一区主播| 国产精品久久久久久婷婷天堂| 国产精品久久久久久亚洲调教| 国产成人亚洲精品| 国产精品第1页| 国产乱肥老妇国产一区二| 国产在线观看精品| 亚洲永久免费观看| 国产成人精品日本亚洲11| 国产精品一区二区三区不卡| 久久99精品国产一区二区三区| 国产精品免费区二区三区观看 | 亚洲黄色成人久久久| 亚洲精品在线视频观看| 亚洲一区二区三区在线观看视频| 中文字幕一区二区三区四区五区六区| 欧美二区在线播放| 97国产一区二区精品久久呦| 欧美在线免费视频| 国产精品青草久久久久福利99| 国产精品天天狠天天看| 亚洲sss综合天堂久久| 国产成人av一区二区三区| 久久久人人爽| 一本色道久久综合亚洲二区三区 | **欧美日韩vr在线| 热99精品里视频精品| 国产精品高清免费在线观看| 91免费国产网站| 黑人中文字幕一区二区三区| 欧美一区二区三区四区五区六区 | 国产中文字幕亚洲| 成人h在线播放| 欧美三日本三级少妇三99| 色综合天天狠天天透天天伊人| 91av视频在线观看| 国产日本欧美一区二区三区| 高清视频一区二区三区| 日本不卡二区高清三区| 久久久久久久久网站| 国产suv精品一区二区| 成人黄色av免费在线观看| 好看的日韩精品视频在线| 一区二区不卡在线视频 午夜欧美不卡'| 久久免费国产精品1| 国产成人欧美在线观看| 91久久大香伊蕉在人线| 日本午夜精品一区二区三区| 97在线视频免费看| 亚洲一区二区三区毛片| 青青成人在线| 4k岛国日韩精品**专区| 91在线观看免费| 清纯唯美一区二区三区| 97精品免费视频| 91在线视频成人| 日本一区精品| 欧美在线一区二区三区四| 亚洲自拍在线观看| 性欧美.com| 国产精品人成电影在线观看| 日韩av电影在线播放| 动漫3d精品一区二区三区| 亚洲精品国产精品国自产观看| 国产91色在线免费| 精品欧美国产| 69av在线视频| 国产精品 日韩| 国产综合在线视频| 国内精品久久国产| 精品日产一区2区三区黄免费| 国产精品久久久久久久av电影 | 国产综合久久久久| 精选一区二区三区四区五区| 成人精品福利视频| 欧美一级免费看| 日韩精品久久久| 91av在线精品| 亚洲最大成人在线| 亚洲wwwav| 日韩欧美亚洲在线| 久久久久久久免费| 日本精品视频在线播放| 精品久久蜜桃| 日韩不卡av| 国产精品私拍pans大尺度在线| 欧美黄色直播| 国产精品露脸av在线| 国产精品v欧美精品v日韩| 久久久久久久影院| 不卡视频一区二区| 午夜精品久久久久久久99热| 成人欧美一区二区三区黑人免费| 中文字幕中文字幕99| 91久久国产自产拍夜夜嗨| 久久久久久高潮国产精品视| 成人情视频高清免费观看电影| 久久久久久久久久国产精品| 肥熟一91porny丨九色丨| 午夜精品一区二区三区视频免费看| 国产高清自拍99| 欧美在线视频导航| 裸模一区二区三区免费| 国产精品久久久久久久久久久久久 | 99久久99久久| 欧美在线视频免费| 欧美一区二区影视| 成人日韩av在线| 久久久亚洲精品视频| 精品国产二区在线| 国产精品偷伦视频免费观看国产| 在线观看日韩片| 国内视频一区| 国产精品视频网址| 久久久久久九九九| 麻豆91蜜桃| 亚洲精品免费在线视频| 欧美一区二区三区……| 麻豆av一区二区| 成人黄色av免费在线观看| 97久久精品视频| 99精品在线直播| 国产精品久久精品| 日韩三级电影网站| 成人在线免费观看一区| 国产成人在线一区二区| 欧美高清在线播放| 国内成+人亚洲| 91久久久久久久| 欧美性资源免费| 先锋影音网一区| 成人免费网站在线看| 人人爽久久涩噜噜噜网站| 一区二区91美女张开腿让人桶| 久久av一区二区| 成人激情春色网| 国产成人精品av| 日日夜夜精品网站| 奇米视频888战线精品播放| 成人精品aaaa网站| 日韩免费av在线| 久久久久久高清| 成人午夜影院在线观看| 国产日韩精品电影| 亚州av一区二区| 中文字幕一区二区三区有限公司| 欧美成人第一区| 91在线视频精品| 国产精品久久久久久久美男| 51午夜精品视频| 久久久久久久久久亚洲| 亚洲欧美国产精品桃花| 欧美高清性xxxxhdvideosex| 国产综合av一区二区三区| 99视频网站| 亚洲自拍小视频| 91久久国产精品91久久性色| 日本久久91av| 久久国产精品久久精品国产| 91在线观看免费高清完整版在线观看| 久久久久国产一区二区三区| 一区二区精品国产| 精品国产电影| 激情久久av| 国产欧亚日韩视频| 国产精品直播网红| 欧美中文在线观看| 宅男av一区二区三区| 亚洲一区二区在| 国产精品一区二区三区在线 | 久久噜噜噜精品国产亚洲综合| 亚洲精品无人区| 久久精品女人的天堂av| 亚洲欧美丝袜| 国产精品专区h在线观看| 韩国福利视频一区| 国产精品一区二区三区久久 | 日本成人在线视频网址| 性欧美xxxx交| 97久久国产精品| 欧美一区二区三区四区在线| 日韩美女视频在线观看| 91福利视频网| 国产91久久婷婷一区二区| 国产成人精品免高潮在线观看| 国产91在线播放精品91| 国产精品白丝jk喷水视频一区| 国产精品国产亚洲伊人久久| 国产精品丝袜久久久久久高清| 91美女片黄在线观看游戏| 99久久久久国产精品免费| 91丝袜脚交足在线播放|