在线看片网址,亚洲精品中文字幕无乱码,欧美日韩中文一区http://www.bjzhda.cnzh-cn曙海教育集團(tuán)論壇http://www.bjzhda.cnRss Generator By Dvbbs.Net[email protected]images/logo.gif曙海教育集團(tuán)論壇關(guān)于F2812中用C語(yǔ)言來(lái)實(shí)現(xiàn)中斷的說(shuō)明http://www.xinguifushi.cn/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)擊可在新窗口打開(kāi)查看ieVectTableInit;
Uint32 *Dest = (void *) &圖片點(diǎn)擊可在新窗口打開(kāi)查看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ù)程序,
×××切記:一定要在主程序的開(kāi)始先聲明該程序:
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.xinguifushi.cn/bbs/dispbbs.asp?BoardID=62&ID=2413&Page=1wangxinxin2010-12-10 11:48:31 

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

 

從圖上可以看到,整個(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)(<>)。另外開(kāi)發(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源程序的名稱(chēng)。預(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ù)寫(xiě)傳播,以及無(wú)用賦值的刪除,等等。

       后一種類(lèi)型的優(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í)行的,但一般卻不可寫(xiě)。


 

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


 

UNIX環(huán)境下主要有三種類(lèi)型的目標(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í)際上是第一種類(lèi)型的目標(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ù)開(kāi)發(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ù)的代碼被放到稱(chēng)作是動(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)擊可在新窗口打開(kāi)查看

從上圖可以看到:


 

預(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.xinguifushi.cn/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)整類(lèi)型, 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.xinguifushi.cn/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á)式的值,因此,直接寫(xiě)出你是如何計(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. 寫(xiě)一個(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)題開(kāi)始討論宏的副作用,例如:當(dāng)你寫(xiě)下面的代碼時(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è)書(shū)呆子是很有用的。只有書(shū)呆子才會(huì)讀C語(yǔ)言課本的附錄去找出象這種
問(wèn)題的答案。當(dāng)然如果你不是在找一個(gè)書(shū)呆子,那么應(yīng)試者最好希望自己不要知道答案。

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

4. 嵌入式系統(tǒng)中經(jīng)常要用到無(wú)限循環(huán),你怎么樣用C編寫(xiě)死循環(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)常聲稱(chēng)這里有幾個(gè)問(wèn)題是那種要翻一下書(shū)才能回答的問(wèn)題,我同意這種說(shuō)法。當(dāng)我寫(xiě)這篇文章時(shí),為了確定語(yǔ)法的正確性,我的確查了一下書(shū)。
但是當(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,也還是能很容易寫(xiě)出功能正確的程序,那么我為什么還要如此看重關(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)生類(lèi)似下面的代碼:
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,寫(xiě)兩段代碼,第一個(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ù)雜的通信芯片寫(xiě)的驅(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編譯器。寫(xiě)代碼去完成這一任務(wù)。

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

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

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

中斷(Interrupts)

11. 中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開(kāi)發(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)有些開(kāi)發(fā)者懂得極少這些東西。不管如何,這無(wú)符號(hào)整型問(wèn)題的答案是輸出是“>6”。原因是當(dāng)表達(dá)式中存在有符號(hào)類(lèi)型和無(wú)符號(hào)類(lèi)型時(shí)所有的操作數(shù)都自動(dòng)轉(zhuǎn)換為無(wú)符號(hào)類(lèi)型。因此-20變成了一個(gè)非常大的正整數(shù),所以該表達(dá)式計(jì)算出的結(jié)果大于6。這一點(diǎn)對(duì)于應(yīng)當(dāng)頻繁用到無(wú)符號(hào)數(shù)據(jù)類(lèi)型的嵌入式系統(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)編寫(xiě)如下:

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ò)我這里能提到的任何解釋?zhuān)谢剡^(guò)頭看一下這些雜志吧!讓?xiě)?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)開(kāi)始討論這樣的一問(wèn)題,看看被面試者是否想到庫(kù)例程這樣做是正確。得到正確的答案固然重要,但解決問(wèn)題的方法和你做決定的基本原理更重要些。

Typedef

15. Typedef 在C語(yǔ)言中頻繁用以聲明一個(gè)已經(jīng)存在的數(shù)據(jù)類(lèi)型的同義字。也可以用預(yù)處理器做類(lèi)似的事。例如,思考一下下面的例子:
#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.xinguifushi.cn/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)一些其他的東西也可以類(lèi)似。* c5 ?! A2 R+ y8 z: }3 r$ y
用C語(yǔ)言描述數(shù)據(jù)結(jié)構(gòu)可以分為以下幾部分:線性表,隊(duì),餞,廣義表,然后是樹(shù),圖,最后還有遞歸,串,查找,排序。其中較為典型的例子有走迷宮,漢諾塔,出入隊(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)算的分類(lèi):
+ 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)體類(lèi)型*/
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類(lèi)型*/
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)    銷(xiāo)毀線性表
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)銷(xiāo)毀線性表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.xinguifushi.cn/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#開(kāi)發(fā)的兩個(gè)基本原則的深入討論http://www.xinguifushi.cn/bbs/dispbbs.asp?BoardID=62&ID=2408&Page=1wangxinxin2010-12-10 11:37:07
  明辨值類(lèi)型和引用類(lèi)型的使用場(chǎng)合

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

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

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

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

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

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

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

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

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

  關(guān)于第1條,Bill Wagner在本條款中提到了“引用類(lèi)型會(huì)給垃圾收集器帶來(lái)負(fù)擔(dān)”這個(gè)表面看似正確的判斷。但是由于box/unbox的效應(yīng),有些情況下,反倒是值類(lèi)型給垃圾收集器帶來(lái)了更多的負(fù)擔(dān)。比如將一些值類(lèi)型放到一個(gè)集合中,然后又頻繁地對(duì)其進(jìn)行讀寫(xiě)操作。如果碰到這種情況,我想“放棄結(jié)構(gòu)而采用類(lèi)”未嘗不是一種更好的做法。事實(shí)上,將一個(gè)用作數(shù)據(jù)存儲(chǔ)的值類(lèi)型(比如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)類(lèi)型具有默認(rèn)的深拷貝語(yǔ)義,沒(méi)有拷貝構(gòu)造器的調(diào)用。而且結(jié)構(gòu)類(lèi)型也沒(méi)有子類(lèi),因此在某種程度上來(lái)講不具有多態(tài)性,也就沒(méi)有C++對(duì)象傳值時(shí)可能出現(xiàn)的切割(slicing)效應(yīng)。但是值拷貝的成本仍然不小。尤其是在這個(gè)值類(lèi)型比較大的情況下,問(wèn)題就比較嚴(yán)重。實(shí)際上,在.NET框架的Design Guidelines for Class Library Developers文檔中,在說(shuō)明什么時(shí)候應(yīng)該使用結(jié)構(gòu)類(lèi)型的時(shí)候,其中提到了一項(xiàng)原則(還有其他一些并行原則)——類(lèi)型實(shí)例數(shù)據(jù)的大小要小于16個(gè)字節(jié)。該文檔主要是從類(lèi)型的運(yùn)行效率層面來(lái)考慮的,而B(niǎo)ill Wagner先生這里的條款主要是從類(lèi)型的設(shè)計(jì)層面來(lái)考慮的。

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

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

實(shí)例31 菜單實(shí)現(xiàn) 96
實(shí)例32 窗口制作 97
實(shí)例33 模擬屏幕保護(hù)程序 100
實(shí)例34 文件讀寫(xiě)基本操作 102
實(shí)例35 格式化讀寫(xiě)文件 105
實(shí)例36 成塊讀寫(xiě)操作 107
實(shí)例37 隨機(jī)讀寫(xiě)文件 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 用畫(huà)線函數(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)畫(huà)制作 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 挽救磁盤(pán)數(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)磁盤(pán)數(shù)據(jù)的整體加密 224
實(shí)例83 揭開(kāi)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 火車(chē)訂票系統(tǒng) 286]]>
關(guān)于C和C++區(qū)別的討論http://www.xinguifushi.cn/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,如何劃分類(lèi)和對(duì)象,但是,具體到一個(gè)功能,還是要用函數(shù)來(lái)實(shí)現(xiàn),不管如何寫(xiě)程序,到了函數(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)楹芏嗄暌郧埃蠹矣X(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)用。

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

    正是因?yàn)榇耍蠹以谏鲜兰o(jì)七十年代,提出了模塊化開(kāi)發(fā)的思想,試圖通過(guò)各個(gè)模塊的獨(dú)立開(kāi)發(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)有可能,把一類(lèi)數(shù)據(jù),以及其方法,從編譯器的角度區(qū)別開(kāi)來(lái),構(gòu)建獨(dú)立模塊,外部模塊僅能訪問(wèn)到它允許訪問(wèn)的方法,其他的方法,全部報(bào)錯(cuò),拒絕編譯呢?

    答案是當(dāng)然可以。大家就這么做了。那么,我們看看,一類(lèi)數(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í)一門(mén)新語(yǔ)言,尤其是開(kāi)發(fā)思路完全不同的語(yǔ)言,是不可想象的,成本太高。大家就想,能不能折中一下,以C的語(yǔ)法為藍(lán)本,開(kāi)發(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ù),僅僅是放在類(lèi)里面而已

]]>
關(guān)于對(duì)c++基本語(yǔ)言的看法http://www.xinguifushi.cn/bbs/dispbbs.asp?BoardID=62&ID=2405&Page=1wangxinxin2010-12-10 11:16:57也許寫(xiě)這篇文章有的人會(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下的開(kāi)發(fā),剛畢業(yè)的自己說(shuō)實(shí)話對(duì)c認(rèn)識(shí)太淺了,我掌握的是在linux下應(yīng)用程序的開(kāi)發(fā),大部分用到了對(duì)文件的讀取,對(duì)指針的操作,而且自己都是在公司前輩的路下沿著開(kāi)發(fā)的。自己根本就沒(méi)有真正的去認(rèn)真想想算法開(kāi)發(fā)一個(gè)應(yīng)用程式。現(xiàn)在想來(lái)真是可悲的很,學(xué)習(xí)c語(yǔ)言如果自己不進(jìn)行程序的算法開(kāi)發(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ì)好的。現(xiàn)在這我話我已經(jīng)深信不疑了,不管是java也好,c#也好還是最新的python等等語(yǔ)言吧,在我看來(lái)都是以c的基礎(chǔ)來(lái)進(jìn)行的,所謂的新無(wú)非是自己不用再想一些函數(shù)庫(kù)德算法了,我承認(rèn)這是一種進(jìn)步,至少是站在別人的肩膀上做事.效率的時(shí)代講究的也是效率這也正是講究效率開(kāi)發(fā)公司對(duì)這些方便語(yǔ)言的鐘情。這是可以理解的事情。不過(guò)這里我要說(shuō)的是c++,這是真正的與c語(yǔ)言接觸緊密但是確實(shí)又非常實(shí)用的語(yǔ)言,人們都說(shuō)c++是個(gè)好東東,可是在開(kāi)發(fā)的時(shí)候卻有時(shí)極力的回避這種語(yǔ)言,最終是因?yàn)閏語(yǔ)言的復(fù)雜性。說(shuō)句我個(gè)人的看法,我覺(jué)得這樣做是不對(duì)的,因?yàn)楦呖萍疾皇且恢写蟊娀闹R(shí),講究的是一個(gè)人或一個(gè)團(tuán)隊(duì)的智慧,就是因?yàn)閏++的復(fù)雜性就不去用它,或是少去用它而是用更多的方便開(kāi)發(fā)語(yǔ)言,這種想法是不好的,因?yàn)槿绻粋(gè)搞程序的人對(duì)算法都不能很好的去自行開(kāi)發(fā),只會(huì)是去沿用別人寫(xiě)好的東西。充其量跟工廠里的機(jī)器裝配工很像,無(wú)非是把基本的一些寫(xiě)好的類(lèi)庫(kù)函數(shù)庫(kù)羅列好了。如果真是這樣這是軟件業(yè)的恥辱,也是中國(guó)軟件業(yè)的恥辱。

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

]]>
用C語(yǔ)言進(jìn)行CGI程序設(shè)計(jì)http://www.xinguifushi.cn/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ǔ)言編寫(xiě),如Shell腳本語(yǔ)言、Perl、Fortran、Pascal、C語(yǔ)言等。但是用C語(yǔ)言編寫(xiě)的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í)際的文本信息開(kāi)始之前先看見(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()或者其他的文件寫(xiě)函數(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)單手段,之所以稱(chēng)為環(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程序的名稱(chēng)。
  QUERY-STRING:當(dāng)使用POST方法時(shí),Form中的數(shù)據(jù)最后放在QUERY-STRING中,傳遞給CGI程序。
  CONTENT-TYPE:傳遞給CGI程序數(shù)據(jù)的MIME類(lèi)型,通常為″applica tion/x-www-form-url encodede″,它是從HTML Form中以POST方法傳遞數(shù)據(jù)給CGI程序的數(shù)據(jù)編碼類(lèi)型,稱(chēng)為URL編碼類(lèi)型。
  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)制值的開(kāi)始,調(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è)空行分開(kāi)。我們已經(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.xinguifushi.cn/bbs/dispbbs.asp?BoardID=62&ID=2403&Page=1wangxinxin2010-12-10 11:13:30
  Flash

  事實(shí)上,F(xiàn)lash中的游戲開(kāi)發(fā)已經(jīng)進(jìn)行了多年的嘗試。但至今為止仍然停留在中、小型游戲的開(kāi)發(fā)上。游戲開(kāi)發(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ù)和開(kāi)發(fā)。

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

  目前國(guó)內(nèi)就有一款完全基于 Flash 制作的網(wǎng)頁(yè)游戲《黑暗契約》。此款游戲遲遲不得開(kāi)放,原因如何?團(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)存緩沖開(kāi)發(fā)了復(fù)雜的管理和寫(xiě)回機(jī)制。黑暗契約服務(wù)器的投入成本會(huì)是以往游戲的3倍。”

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

 ]]>
C語(yǔ)言之父Dennis Ritchiehttp://www.xinguifushi.cn/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)軟件研究部門(mén),目前他是朗訊技術(shù)公司系統(tǒng)軟件研究部門(mén)的領(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)里奇為什么使用他使用的方式開(kāi)發(fā)了C語(yǔ)言的時(shí)候,里奇回答說(shuō)“這樣做看上去很好”,他說(shuō)任何人在同一地方、同一時(shí)間會(huì)像他那樣做的。但是其他許多人認(rèn)為這只不過(guò)反映出了里奇的謙虛。C++的開(kāi)發(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)的微軟為他們的用戶和開(kāi)發(fā)者提供了與Unix相容的工具和C語(yǔ)言編譯器。

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

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

Dennis MacAlistair=

Dennis MacAlistair Ritchie

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

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

換一個(gè)角度

變量類(lèi)別 子類(lèi)別
靜態(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)(注意自己寫(xiě)的*.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的單詞開(kāi)始的,一開(kāi)始總會(huì)覺(jué)得把語(yǔ)句一并寫(xiě)在main里不是挺好的么,為什么偏擇出去。其實(shí)這是因?yàn)閷?duì)函數(shù)還不夠熟練,否則函數(shù)的運(yùn)用會(huì)給我們編程帶來(lái)極大的便利。我們要知道函數(shù)的返回值類(lèi)型,參數(shù)的類(lèi)型,以及調(diào)用函數(shù)時(shí)的形式。事先的函數(shù)說(shuō)明也能起到一個(gè)提醒的好作用。所謂形參和實(shí)參,即在調(diào)用函數(shù)時(shí)寫(xiě)在括號(hào)里的就是實(shí)參,函數(shù)本身用的就是形參,在畫(huà)流程圖時(shí)用平行四邊形表示傳參。

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

例子:
 



數(shù)組:

分為一維數(shù)組和多維數(shù)組,其存儲(chǔ)方式畫(huà)為表格的話就會(huì)一目了然,其實(shí)就是把相同類(lèi)型的變量有序的放在一起。因此,在處理比較多的數(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)展開(kāi),就會(huì)越來(lái)越熟悉,以后自己編寫(xiě)一個(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 程序開(kāi)發(fā)教程及技術(shù)討論專(zhuān)貼http://www.xinguifushi.cn/bbs/dispbbs.asp?BoardID=62&ID=2400&Page=1wangxinxin2010-12-10 11:07:00西門(mén)子x65/x75上的 ELF 程序大家已經(jīng)見(jiàn)識(shí)過(guò)了,你有沒(méi)想過(guò)寫(xiě)出自己的 ELF 程序呢?如果你有C語(yǔ)言基礎(chǔ),那么加入 ELF 程序開(kāi)發(fā)的隊(duì)伍吧。
要在西門(mén)子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ī)型,看程序怎么寫(xiě)的了8-) )
下面進(jìn)入正題

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

3.如何用 IAR 編寫(xiě) ELF
4.例1:內(nèi)存和文件的操作
5.例2:屏幕輸出和鍵盤(pán)控制
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è)。填寫(xiě)正確的油箱以后,就會(huì)把使用序列號(hào)發(fā)給你。安裝沒(méi)說(shuō)的了吧,一路下一步,下一步,等等。

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

3.如何用 IAR 編寫(xiě) ELF
開(kāi)始一個(gè) ELF 程序的編寫(xiě),還是比較簡(jiǎn)單 :P
在菜單上選擇 “Project->Create New Project”
然后選添加"Project->Add Files"把你用其他IDE寫(xiě)好的C程序添加進(jìn)來(lái)就可以了
工程必須還要有 func.asm (入口點(diǎn)) 和 div.r79 (這個(gè)好象莫必要?我也不太清楚,我是業(yè)余的:( )
C程序知道怎么寫(xiě),問(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);
        //表示按記錄文件打開(kāi),數(shù)據(jù)添加到文件末尾,如果文件不存在則創(chuàng)建之
        //如果為 handle=fopen (fname,A_ReadOnly+A_BIN, 0,err);
        //則表示按只讀方式打開(kāi)文件,具體常數(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:屏幕輸出和鍵盤(pán)控制
通過(guò)導(dǎo)航鍵控制屏幕上的符號(hào)移動(dòng),長(zhǎng)按紅鍵退出。本例子基于 TED- A (c) Of rst7
看本例時(shí)最好從下往上看:)

創(chuàng)建 main.c 如下后添加到你的工程里:
//main.c
//屏幕和鍵盤(pán)處理
#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.xinguifushi.cn/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á)的是一種詛咒,而不是判斷。翻譯稱(chēng)《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ǔ)軟件是指這樣一類(lèi)軟件,其主要任務(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ǔ)軟件的源代碼里,常常看到一些丑陋的設(shè)計(jì),看到一些變態(tài)的黑客技巧,在其他的領(lǐng)域里,這是不被鼓勵(lì)的,但是在基礎(chǔ)軟件中,這就是合理的,可以接受的。

     C語(yǔ)言目前仍在一些領(lǐng)域里堅(jiān)挺,在操作系統(tǒng)、虛擬機(jī)和設(shè)備驅(qū)動(dòng)程序開(kāi)發(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è)一般水平的開(kāi)發(fā)者來(lái)說(shuō),他寫(xiě)的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ō),素以速度著稱(chēng)、并且為了速度放棄了很多東西的C語(yǔ)言,現(xiàn)在比裝備齊全的Java只快不到一倍了。這還不算,如果考慮到新的計(jì)算環(huán)境,C語(yǔ)言的速度優(yōu)勢(shì)有可能僅僅是一個(gè)錯(cuò)覺(jué)。因?yàn)椋澜缟现挥泻苌俚娜擞心芰υ诙郈PU計(jì)算平臺(tái)上用C語(yǔ)言寫(xiě)出又快又正確的大程序,在這些人中間,又只有很少很少的人有能力用C語(yǔ)言寫(xiě)出一個(gè)在大型的、異構(gòu)的網(wǎng)絡(luò)環(huán)境下能夠充分發(fā)揮各節(jié)點(diǎn)計(jì)算能力的大規(guī)模并行程序。也就是說(shuō),你也許有能力把程序效能提高一倍,從而充分發(fā)揮一臺(tái)價(jià)值6000元人民幣的PC的計(jì)算潛力,為客戶節(jié)省1000元錢(qián)。但如果是在一個(gè)由1000臺(tái)機(jī)器組成的大型異構(gòu)網(wǎng)絡(luò)并行計(jì)算的環(huán)境下,你寫(xiě)的C程序恐怕性能還會(huì)遠(yuǎn)遠(yuǎn)低于對(duì)應(yīng)的Java程序,更不要說(shuō)巨大的后期維護(hù)成本,而由此帶來(lái)的損失可能是1000萬(wàn)或者更多。

    其次是經(jīng)驗(yàn)。很多人都宣稱(chēng)自己的C功力如何如何了得,但是實(shí)際上,即使是真正的C高手也不得不花相當(dāng)可觀的時(shí)間來(lái)尋找并且調(diào)試錯(cuò)誤,尤其是內(nèi)存方面的錯(cuò)誤。大部分用C寫(xiě)的上規(guī)模的軟件都存在一些內(nèi)存方面的錯(cuò)誤,需要花費(fèi)大量的精力和時(shí)間把產(chǎn)品穩(wěn)定下來(lái)。這還沒(méi)有把安全方面的缺陷考慮在內(nèi),現(xiàn)在大部分的開(kāi)發(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)單,提供不了高層的抽象,因此在開(kāi)發(fā)者只能從一些“并發(fā)原語(yǔ)”出發(fā)去構(gòu)造并發(fā)程序,這跟用鉛筆刀鋸大樹(shù)沒(méi)什么分別,直截了當(dāng)?shù)卣f(shuō),大部分C程序員根本沒(méi)有能力編寫(xiě)高效無(wú)缺陷的并發(fā)程序。

    所以殘酷的事實(shí)是,當(dāng)一個(gè)人說(shuō)自己的C語(yǔ)言如何了得,經(jīng)驗(yàn)如何豐富時(shí),非常可能他說(shuō)的是,自己在用C語(yǔ)言寫(xiě)單機(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)編寫(xiě)高質(zhì)量的大規(guī)模軟件,是只有真正的專(zhuān)家團(tuán)隊(duì)才能完成的工作。如果你曾經(jīng)有過(guò)連續(xù)數(shù)日苦苦追蹤和調(diào)試一個(gè)內(nèi)存泄露、或者線程錯(cuò)誤的經(jīng)歷,你就會(huì)明白,你可能不是這樣的專(zhuān)家。

    相比之下,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ǔ)言寫(xiě)出優(yōu)秀基礎(chǔ)軟件的人固然不多,能用Java寫(xiě)出來(lái)的人恐怕更少。Java有好幾百萬(wàn)開(kāi)發(fā)者,但是他們?cè)诟墒裁矗看蟛糠质侨ジ闫髽I(yè)級(jí)開(kāi)發(fā)、Web開(kāi)發(fā)了,有多少人真的理解Java的內(nèi)存模型?有多少人能夠熟練使用concurrent包中提供的那些工具?很多使用Java多年的人沒(méi)有寫(xiě)過(guò)socket程序,不了解Java多線程的開(kāi)銷(xiāo),不清楚如何進(jìn)行性能診斷和調(diào)優(yōu),而這些在寫(xiě)基礎(chǔ)軟件的時(shí)候是必備的技能。大部分Java程序員在剛剛學(xué)會(huì)Java之后就轉(zhuǎn)向Web開(kāi)發(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ǔ)軟件開(kāi)發(fā)工作的尖兵,不但難度很大,而且必須花費(fèi)足夠的時(shí)間。

2. Java的內(nèi)存消耗太大。對(duì)于系統(tǒng)級(jí)程序來(lái)說(shuō),內(nèi)存消耗大,就意味著cache命中率降低,與磁盤(pán)交換數(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ǔ)軟件開(kāi)發(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)用軟件的開(kāi)發(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)喝酒,放下筷子罵娘,甩開(kā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)題要像宋襄公,要張榜檄文,要名正言順,要禮儀之邦,要把架子拉開(kāi)了,把譜兒擺足了。Java的口號(hào)是,不管劈不劈的死,先把你小子感動(dòng)了再說(shuō)。 這套繁瑣的東西,對(duì)于基礎(chǔ)軟件開(kāi)發(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寫(xiě)程序?

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

]]>
一個(gè)簡(jiǎn)單的一箭穿心程序http://www.xinguifushi.cn/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;
/*畫(huà)心*/
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);
}
}  
/*畫(huà)箭頭*/
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.xinguifushi.cn/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ù)
    編寫(xiě)一個(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 回車(chē)
        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.xinguifushi.cn/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)單元開(kāi)始的四個(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的類(lèi)型和ptrold的類(lèi)型相同,ptrnew所指向的類(lèi)型和ptrold所指向的類(lèi)型也相同。ptrnew的值將比ptrold的值增加了n乘sizeof(ptrold所指向的類(lèi)型)個(gè)字節(jié)。就是說(shuō),ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向高地址方向移動(dòng)了n乘sizeof(ptrold所指向的類(lèi)型)個(gè)字節(jié)。 一個(gè)指針ptrold減去一個(gè)整數(shù)n后,結(jié)果是一個(gè)新的指針ptrnew,ptrnew的類(lèi)型和ptrold的類(lèi)型相同,ptrnew所指向的類(lèi)型和ptrold所指向的類(lèi)型也相同。ptrnew的值將比ptrold的值減少了n乘sizeof(ptrold所指向的類(lèi)型)個(gè)字節(jié),就是說(shuō),ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向低地址方向移動(dòng)了n乘sizeof(ptrold所指向的類(lèi)型)個(gè)字節(jié) 運(yùn)算符&和* 這里&是取地址運(yùn)算符,*是...書(shū)上叫做"間接運(yùn)算符"。 &a的運(yùn)算結(jié)果是一個(gè)指針,指針的類(lèi)型是a的類(lèi)型加個(gè)*,指針?biāo)赶虻念?lèi)型是a的類(lèi)型,指針?biāo)赶虻牡刂仿铮蔷褪莂的地址。 *p的運(yùn)算結(jié)果就五花八門(mén)了。總之*p的結(jié)果是p所指向的東西,這個(gè)東西有這些特點(diǎn):它的類(lèi)型是p指向的類(lèi)型,它所占用的地址是p所指向的地址。例五: inta=12; intb; int*p; int**ptr; p=&a; //&a的結(jié)果是一個(gè)指針,類(lèi)型是int*,指向的類(lèi)型是int,指向的地址是a的地址。 *p=24; //*p的結(jié)果,在這里它的類(lèi)型是int,它所占用的地址是p所指向的地址,顯然,*p就是變量a。 ptr=&p; //&p的結(jié)果是個(gè)指針,該指針的類(lèi)型是p的類(lèi)型加個(gè)*,在這里是int **。該指針?biāo)赶虻念?lèi)型是p的類(lèi)型,這里是int*。該指針?biāo)赶虻牡刂肪褪侵羔榩自己的地址。 *ptr=&b; //*ptr是個(gè)指針,&b的結(jié)果也是個(gè)指針,且這兩個(gè)指針的類(lèi)型和所指向的類(lèi)型是一樣的,所以用&b來(lái)給*ptr賦值就是毫無(wú)問(wèn)題的了。 **ptr=34; //*ptr的結(jié)果是ptr所指向的東西,在這里是一個(gè)指針,對(duì)這個(gè)指針再做一次*運(yùn)算,結(jié)果就是一個(gè)int類(lèi)型的變量。 指針表達(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.xinguifushi.cn/bbs/dispbbs.asp?BoardID=62&ID=2395&Page=1wangxinxin2010-12-10 10:12:35

數(shù)組是由具有相同類(lèi)型的數(shù)據(jù)元素組成的有序集合。數(shù)組是由數(shù)組名來(lái)表示的,數(shù)組中的數(shù)據(jù)由特定的下標(biāo)來(lái)唯一確定。引入數(shù)組的目的,是使用一塊連續(xù)的內(nèi)存空間存儲(chǔ)多個(gè)類(lèi)型相同的數(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)存放類(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ù)均為字符類(lèi)型(char),最后一個(gè)單元為'\0'0x00[size=#]),用來(lái)表示字符串的結(jié)束。C51函數(shù)庫(kù)中提供了專(zhuān)門(mén)對(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ù)組就稱(chēng)為二維數(shù)組。其定義的一般形式為:

類(lèi)型說(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開(kāi)始,最大為5,6;列下標(biāo)也從0開(kāi)始,最大為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久久香蕉| 亚洲欧美大片 | 成年人免费在线视频网站 | 大胆gogo999亚洲肉体艺术 | 高清国产美女一级a毛片录 高清国产亚洲va精品 | 欧美视频综合 | 成人三级在线播放 | 午夜看毛片 | 午夜毛片免费观看视频 | 日韩一级特黄毛片在线看 | 国产91网 | 永久免费不卡在线观看黄网站 | 一级不卡毛片免费 | 欧美精品网址 | 国产午夜亚洲精品第一区 | 美女张开腿让我 | 97青草香蕉依人在线播放 | 久久99精品久久久久久秒播放器 | a毛片免费全部在线播放毛 a毛片免费视频 | 米奇777第四久久久99 | 国产精品久久久久久久久久免费 | 欧美日韩在线视频观看 | 日韩一级生活片 | 一级毛片在线视频 | 一区二区三区不卡视频 | 12345国产精品高清在线 | 乱子伦xxxx| 在线国产欧美 | 精品久久香蕉国产线看观看亚洲 | 久久久国产精品福利免费 | 国产在线a不卡免费视频 | 亚洲日本中文字幕在线 | 久久国产成人精品 | 国产精品久久免费 | 高清午夜线观看免费 | 中文字幕亚洲一区二区v@在线 | 国产亚洲精品激情一区二区三区 | 日本美女一区二区三区 | 国内自拍网址 | 日韩a一级欧美一级 | 日韩国产欧美成人一区二区影院 |