﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-C++ Programmer</title><link>http://www.cppblog.com/suiaiguo/</link><description>天行健，君子以自强不息；
地势坤，君子以厚德载物</description><language>zh-cn</language><lastBuildDate>Wed, 22 Apr 2026 01:28:24 GMT</lastBuildDate><pubDate>Wed, 22 Apr 2026 01:28:24 GMT</pubDate><ttl>60</ttl><item><title>英语发音规则</title><link>http://www.cppblog.com/suiaiguo/archive/2009/12/16/103323.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Wed, 16 Dec 2009 07:10:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/12/16/103323.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/103323.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/12/16/103323.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/103323.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/103323.html</trackback:ping><description><![CDATA[<pre>1 元音:
1) [i:] 字母组合:ee ea e ie
three tree green sheep meet beef see seek
eat tea meat leave lead teacher team mean speak clean please
he she me
piece receive ceiling
2) [i] 发音字母 i y e
sit picture it is list six mix fix fit pig big build miss
myth many twenty happy dictionary
defect decide delicious
3) [] 发音字母 a
bag hand and ant happy hat map mad bad black back glad flag shall man
4) [e] 字母组合 ea e a
head bread pleasure
elephant electric remember sell shell lesson better bed desk hotel yes
many any
5) [&#949;:] 字母组合ir ur ear ur or
girl shirt skirt thirty thirteen third bird
turn burn murder nurse turtle Thursday burger
learn earn earth heard
term her nerd serve
work worm work world
6) [&#949;] 字母组合 er or ou ar o a e u
teacher leader remember player speaker farmer powder
doctor actor mayor author tractor
delicious gracious pleasure
familiar collar dollar
together tomorrow today shallop lesson Washington control polite around account ago elephant manta banana Canada Japan china
men listen
famulus Saturday
7) [a:] 字母组合 ar a
car farm card arm garden
fast class last glass plant aunt calm
8) [] 发音字母 u o ou oo
up supper lunch fun gun hunt cup bus
come mother dose brother love above
trouble rough flourish
blood flood
9) []字母组合 al or au our ar
small wall talk tall hall ball call walk
short more lord horse for forty sport door floor store
author caught autumn
four mourn court bought
warm quarrel quarter
10) [] 发音字母 o a
hot lost lot fox box mop hop loss collar not
want wash
11) [u:] 字母组合 oo o u
food moon room gloom broom doom goose tooth
shoe do two
true truth blue full
12) [u] 字母组合 oo ou u o
look good foot book
should could
put full bull pull push
women whose
13) [ei] 发音字母 a ay ea ai ey
name cake late gate plane April
play say may way
great break
rain paint plain
they grey
14) [ai] 发音字母 i y
bike fine find die nine light night high
my try fly eye
15) [au] 字母组合 ou ow
house out flour ground account count sound loud around mouse
flower down now cow how town
16) [&#949;u] 发音字母 o ow oa
home cold go no phone host ghost
know low below grow blow show flow
boat coat goal
17) [] 字母组合oy oi
boy toy joy
oil soil voice choice
18) [i&#949;] 字母组合 eer
beer deer ear idea near here fierce
19) [] 字母组合ear air
pear bear chair air fair care there where
20) [u&#949;] hour tour poor flower shower
2 容易混淆的元音
[A] [e]
bad bed hand head man men land lend pan pen sad said
[i：] [ei]
real rail greet great mean main read raid
[e] [ai]
bet bite red write said side head hide
[aU] [R：]
house horse loud lord south sauce cloud clause now nor count corn
[aU] [Q]
found fond down done gown gone town ton
3辅音
1) [p] pen pear play pig pour pull push
2) [b] book big boot bike bread break
3) [t] tree two ten ton town twenty city
4) [d] door dull desk dose do dog dictionary
5) [k] king kite key look cook book kitchen sky (发音字母k)
card cat cream correct climb come account accept (发音字母c)
fox box oxygen x-ray (发音字母x)
school schedule schema (字母组合ch)
6) [g] girl good goal goat grade long language
7) [m] man make moon morning move come comb
8) [n] pen ten nine fine night noon moon clean
9) [N] uncle bank English think thank junk
sing king morning evening
10) [l] long land lend lord fly flag black
world cold could goal soul
11) [r] read red right run room write
12) [f] five fly fine flag frog fog roof knife life wife
cough laugh rough physic photo phone
13) [v] very evening even every voice vest
of
14) [s] six sit student same seat kiss miss case scarf (发音字母s)
license city cease cedar ceiling celebrate (发音字母c)
licence piece juice science lance space ace (字母组合ce)
15) [z] zoo zebra zero zap
close nose hose suppose pause those whose
16) [W] think thank three thirty tooth mouth
17) [T] that this those these though
18) [F] sheep shoulder ship shoe she brush wash
nation attention station
social special
sure
19) [V] pleasure
20) [h] hot hop home house horse how who
21) [w] when what where window wind wood
22) [j] yes year yell you your yolk yellow
23) [tF] child chicken china chair lunch ouch catch teach
24) [dV] age language cabbage vegetable stage bridge
joy enjoy join July June junk
25) [tr] tree country try treat track trunk
26) [dr] dry dream drop drive drink
27) [ts] students boots boats goats nuts
28) [dz] goods woods moods hoods
4容易混淆的辅音
[v] [w]
vest west vet wet vine wine very well
[s] [W]
sink think mass math miss myth sort sought
[z] [T]
close cloth breeze breathe
[n] [N]
thin thing sin sing ran rang ban bang win wing
添加一点:
9) []字母组合 al or au our ar aw
small wall talk tall hall ball call walk
short more lord horse for forty sport door floor store
author caught autumn
four mourn court bought
warm quarrel quarter
draw saw flaw
23) [tF] child chicken china chair lunch ouch teach (字母组合ch）
catch watch match （字母组合tch)
5 字母，组合音节发音规律
1）a [ei] [&#230;] [[] [a:] [R]
late private grade bake grape nation station page
active hand bank fan parent family glad flag
accept about above formative machine cinema
fast last glass class past father
wash what watch want
2）e [i:] [e] [i] [[] 不发音
appreciate extremely secret she me he
letter left message generate pebble
decide pretty previous result restore
problem prosperous student confident
active table late wife store lecture
3）i [ai] [i]
high price library ice cream wife size line
fist pick chicken piano fianc&#233; city unit
4）o [[J] [J:] [Q] [[] [R]
lode host cold note okay old home
lose do who whose prove
love some other mother honey company
today tomorrow together control collect
lost hot mock office soft honest
5）u [ju] [u] [Q] [[]
university refuse unique universe huge
put push pull full bull
but brush bucket duck bubble
support suggest
6）c [k] [s]
country camp camera courage cable
city ceiling celebrate cell cease
7）g [g] [dV] [N]
girl grade glass glade bag flag
village vegetable bridge gentleman gym
long song sing morning evening
8) l [l] 读音不同
listen learn language collect English gorilla
world cold soil tall sell cool animal
9) n [n] [N]
moon night noodle number
uncle hungry angry young
10) r [r] [[](美语发音)
right read write grade progress
card board door floor form north
11）y [j] [i] [ai]
yellow year yell young yolk
university country pretty happy
dyke dying fly buy by my
12）ar [a:] [[] [R:]
farm card garden mark
dollar
warm quarrel quarter
13) ea [i:] [e] [ei] [i[]
cease season breathe feature meat please
bread breast breath meadow weather
great break
idea realize
14) ear [[:] [i[]
learn earth earn heard
hear near clear ear fear
15) er [[:] [[] [i[]
deserve serve her person
teacher driver anger singer
serious experience mysterious fierce
16） ere [i[] [Z[]
here mere fere sere
there
17) ir [[:] [ai]
shirt girl skirt
admire desire
18) oo [u:] [u] [Q] [R:]
room tool cool moon noon goof food
good foot stood wood wool cook wood book
blood flood
door floor
19) or [ R:] [[:] [[]
short form corn born for
work world worm word worst
tractor doctor actor sector senior senator
20) oor [ R:] [J[]
door floor
moor poor boor
21) our [J[] [R:]
hour tour flour bourn lour
pour court four mourn
22) ou [au] [Q] [[]
house mouth mouse sound found
enough trouble touch
delicious gracious prosperous
23) ow [[J] [au]
window meadow know show low
now town how down cow
24) se [z] [s]
nose suppose gose lose pose rose
mouse house
25) th [W] [T]
thank think thought cloth
clothes that this then than
26) sion [F[n] [V[n]
propulsion tension progression passion
protrusion provision conclusion television
27) tion [F[n] [ tF[n](不常见)
station nation translation attention
question
6关于语音的几个概念:
Phonics 是一种(方法), 是教育学习者从字母排列中去拼读出单个字来.
AHD表示美语发音,The American Heritage Dictionary of the English Language（简称AHD）
KK音标是一套(注音符号系统),是由John Samuel Kenyon 和 John Albert Knott两位美国学者共同编著的发音词典A Pronouncing Dictionary of American1956中用于标注美式发音的符号系统, 这是一套最常用的也是最权威的注音法，从此人们把美语标准发音惯称为KK音标。
DJ是根据英国学者Daniel Jones编的英语发音字典 (English Pronouncing Dictionary, 1963)中的标音而来.
英式读音根据的是English Pronouncing Dictionary 《英语正音辞典》。它们代表了被称为&#8220;Received Pronuciation&#8221;（RP）（标准读音）的读音，这在受过教育的英国人尤其是南部英格兰人中通用。
1888年国际语音协会 (International Phonetic Association) 的语言学家便制定出一套可国际通用的语音符号叫国际音标符号 (IPA—International Phonetic Alphabet)，希望以一个符号代表一音，并避免各人使用一套自己的符号所产生的不便。
国内的英文字典里最常见的音标为英式发音的国际音标 (DJ) 和美式发音的KK音标，前者乃根据Daniel Jones编的英语发音字典 (English Pronouncing Dictionary, 1963)，后者则是根据John S. Kenyon &amp; Thomas A. Knott二氏的美语发音字典 (A Pronouncing Dictionary of American English, 1956)。值得一提的是，KK音标所使用的符号均从前面提到的国际音标符号 (IPA) 而来，Kenyon &amp; Knott二氏仅将其中适用于美式英语的符号截取出来。
音素: 音的最小单位,英语中有48个音素.
音节: 由元音和辅音构成的发音单位.
元音: 发音响亮,是乐音,口腔中气流不受阻碍,是音节的主要组成部分.英语中有20个元音. 辅音: 发音不响亮,是噪音,口腔中气流受到阻碍,不是音节的重要组成部分,英语中有28个辅音.
开音节: 1)辅音+元音+辅音+不发音e kite cake name bike make take home plane shine
2)辅音+元音 he hi go no do be tree three hello
闭音节: 1)辅音+元音+辅音 sit bed bad bag hot hop let mad map head
2)元音+辅音 it is of in on up out ant </pre>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/103323.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-12-16 15:10 <a href="http://www.cppblog.com/suiaiguo/archive/2009/12/16/103323.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程编程浅析（3）——多线程的互斥与同步</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/24/91045.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Fri, 24 Jul 2009 07:14:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/24/91045.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/91045.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/24/91045.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/91045.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/91045.html</trackback:ping><description><![CDATA[在进行多线程编程时，难免还要碰到两个问题，那就线程间的互斥与同步：<br>线程同步是指线程之间所具有的一种制约关系，一个线程的执行依赖另一个线程的消息，当它没有得到另一个线程的消息时应等待，直到消息到达时才被唤醒。<br>线程互斥是指对于共享的进程系统资源，在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时，任何时刻最多只允许一个线程去使用，其它要使用该资源的线程必须等待，直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步（下文统称为同步）。<br><br>线程间的同步方法大体可分为两类：用户模式和内核模式。顾名思义，内核模式就是指利用系统内核对象的单一性来进行同步，使用时需要切换内核态与用户态，而用户模式就是不需要切换到内核态，只在用户态完成操作。<br>用户模式下的方法有：原子操作（例如一个单一的全局变量），临界区。内核模式下的方法有：事件，信号量，互斥量。<br>下面我们来分别看一下这些方法：<br><br><strong>原子操作（全局变量）：</strong>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ThreadProcess()<br><img id=Codehighlighter1_112_258_Open_Image onclick="this.style.display='none'; Codehighlighter1_112_258_Open_Text.style.display='none'; Codehighlighter1_112_258_Closed_Image.style.display='inline'; Codehighlighter1_112_258_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_112_258_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_112_258_Closed_Text.style.display='none'; Codehighlighter1_112_258_Open_Image.style.display='inline'; Codehighlighter1_112_258_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_112_258_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_112_258_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_139_206_Open_Image onclick="this.style.display='none'; Codehighlighter1_139_206_Open_Text.style.display='none'; Codehighlighter1_139_206_Closed_Image.style.display='inline'; Codehighlighter1_139_206_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_139_206_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_139_206_Closed_Text.style.display='none'; Codehighlighter1_139_206_Open_Image.style.display='inline'; Codehighlighter1_139_206_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_139_206_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_139_206_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Sub&nbsp;&nbsp;Thread&nbsp;Tick&nbsp;%5d!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,(i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Exit&nbsp;Sub&nbsp;Thread!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_298_599_Open_Image onclick="this.style.display='none'; Codehighlighter1_298_599_Open_Text.style.display='none'; Codehighlighter1_298_599_Closed_Image.style.display='inline'; Codehighlighter1_298_599_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_298_599_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_298_599_Closed_Text.style.display='none'; Codehighlighter1_298_599_Open_Image.style.display='inline'; Codehighlighter1_298_599_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_298_599_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_298_599_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;ThreadID;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hThread</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateThread(NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPTHREAD_START_ROUTINE)ThreadProcess,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ThreadID);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(ThreadData)<br><img id=Codehighlighter1_457_529_Open_Image onclick="this.style.display='none'; Codehighlighter1_457_529_Open_Text.style.display='none'; Codehighlighter1_457_529_Closed_Image.style.display='inline'; Codehighlighter1_457_529_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_457_529_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_457_529_Closed_Text.style.display='none'; Codehighlighter1_457_529_Open_Image.style.display='inline'; Codehighlighter1_457_529_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_457_529_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_457_529_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;is&nbsp;waiting&nbsp;for&nbsp;Sub&nbsp;Thread!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;Finished!&nbsp;\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>&nbsp;&nbsp;&nbsp;在上面的程序中，我利用了全局变量ThreadData来进行线程间的同步，当子线程结束时改变该值，而父线程则循环判断该值来确认子线程是否已经结束，当子线程结束时，父线程才继续进行下面的操作。<br><br><strong>临界区（Critical Section）</strong> </p>
<p>保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区，那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起，并一直持续到进入临界区的线程离开。临界区在被释放后，其他线程可以继续抢占，并以此达到用原子方式操作共享资源的目的。 </p>
<p>临界区包含两个操作原语：<br>&nbsp;EnterCriticalSection（） 进入临界区 <br>&nbsp;LeaveCriticalSection（） 离开临界区 </p>
<p>EnterCriticalSection（）语句执行后代码将进入临界区以后无论发生什么，必须确保与之匹配的LeaveCriticalSection（）都能够被执行到。否则临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快，但却只能用来同步本进程内的线程，而不可用来同步多个进程中的线程。 </p>
<p><br><strong>事件（Event）</strong> <br>&nbsp;&nbsp; <br>事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。 </p>
<p>信号量包含的几个操作原语： <br>&nbsp; 　　CreateEvent（） &nbsp;&nbsp;&nbsp;创建一个信号量 <br>&nbsp; 　　OpenEvent（） &nbsp;&nbsp;&nbsp;打开一个事件 <br>&nbsp; 　　SetEvent（） &nbsp;&nbsp;&nbsp;回置事件 <br>&nbsp; 　　WaitForSingleObject（） &nbsp;&nbsp;等待一个事件 <br>&nbsp; 　　WaitForMultipleObjects（）　&nbsp;等待多个事件 </p>
<p>WaitForMultipleObjects 函数原型： <br>&nbsp; 　　WaitForMultipleObjects（ <br>&nbsp; 　　IN DWORD nCount, // 等待句柄数 <br>&nbsp; 　　IN CONST HANDLE *lpHandles, //指向句柄数组 <br>&nbsp; 　　IN BOOL bWaitAll, //是否完全等待标志 <br>&nbsp; 　　IN DWORD dwMilliseconds //等待时间 <br>&nbsp; 　　） <br>&nbsp;<br>参数nCount指定了要等待的内核对象的数目，存放这些内核对象的数组由lpHandles来指向。fWaitAll对指定的这nCount个内核对象的两种等待方式进行了指定，为TRUE时当所有对象都被通知时函数才会返回，为FALSE则只要其中任何一个得到通知就可以返回。dwMilliseconds在这里的作用与在WaitForSingleObject（）中的作用是完全一致的。如果等待超时，函数将返回WAIT_TIMEOUT。&nbsp;<br>&nbsp;&nbsp; <br>事件可以实现不同进程中的线程同步操作，并且可以方便的实现多个线程的优先比较等待操作，例如写多个WaitForSingleObject来代替WaitForMultipleObjects从而使编程更加灵活。&nbsp;<br>&nbsp;&nbsp; <br><strong>互斥量（Mutex）</strong> <br>&nbsp;&nbsp; <br>互斥量跟临界区很相似，只有拥有互斥对象的线程才具有访问资源的权限，由于互斥对象只有一个，因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出，以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享，而且可以在不同应用程序的线程之间实现对资源的安全共享。 <br>&nbsp;&nbsp; <br>&nbsp; 　　互斥量包含的几个操作原语： <br>&nbsp; 　　CreateMutex（） &nbsp;&nbsp; 创建一个互斥量 <br>&nbsp; 　　OpenMutex（） &nbsp;&nbsp; 打开一个互斥量 <br>&nbsp; 　　ReleaseMutex（） &nbsp;&nbsp; 释放互斥量 <br>&nbsp; 　　WaitForMultipleObjects（） 等待互斥量对象&nbsp;<br>&nbsp;&nbsp;&nbsp;<br><strong>信号量（Semaphores）</strong> </p>
<p>信号量对象对线程的同步方式与前面几种方法不同，信号允许多个线程同时使用共享资源，这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源，但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore（）创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数，每增加一个线程对共享资源的访问，当前可用资源计数就会减1，只要当前可用资源计数是大于0的，就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目，不能在允许其他线程的进入，此时的信号量信号将无法发出。线程在处理完共享资源后，应在离开的同时通过ReleaseSemaphore（）函数将当前可用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。 </p>
<p>PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数，S大于等于零时代表可供并发进程使用的资源实体数，但S小于零时则表示正在等待使用共享资源的进程数。 </p>
<p>&nbsp;P操作申请资源： <br>&nbsp; 　　（1）S减1； <br>&nbsp; 　　（2）若S减1后仍大于等于零，则进程继续执行； <br>&nbsp; 　　（3）若S减1后小于零，则该进程被阻塞后进入与该信号相对应的队列中，然后转入进程调度。 </p>
<p>&nbsp;V操作释放资源： <br>&nbsp; 　　（1）S加1； <br>&nbsp; 　　（2）若相加结果大于零，则进程继续执行； <br>&nbsp; 　　（3）若相加结果小于等于零，则从该信号的等待队列中唤醒一个等待进程，然后再返回原进程继续执行或转入进程调度。 <br>&nbsp;&nbsp; <br>&nbsp; 　　信号量包含的几个操作原语： <br>&nbsp; 　　CreateSemaphore（） &nbsp;创建一个信号量 <br>&nbsp; 　　OpenSemaphore（） &nbsp;打开一个信号量 <br>&nbsp; 　　ReleaseSemaphore（） &nbsp;释放信号量 <br>&nbsp; 　　WaitForSingleObject（） &nbsp;等待信号量&nbsp;<br>&nbsp;&nbsp;&nbsp;</p>
<p>信号量的使用特点使其更适用于对Socket（套接字）程序中线程的同步。例如，网络上的HTTP服务器要对同一时间内访问同一页面的用户数加以限制，这时可以为每一个用户对服务器的页面请求设置一个线程，而页面则是待保护的共享资源，通过使用信号量对线程的同步作用可以确保在任一时刻无论有多少用户对某一页面进行访问，只有不大于设定的最大用户数目的线程能够进行访问，而其他的访问企图则被挂起，只有在有用户退出对此页面的访问后才有可能进入。&nbsp;<br>&nbsp;<br>因为它们的使用方法都很类似，下面我结合起来给出一个简单的示例：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CRITICAL_SECTION&nbsp;csPrint;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;临界区<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">HANDLE&nbsp;evtPrint;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;事件信号,标记事件是否已发生<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">HANDLE&nbsp;mtxPrint;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;互斥信号,如有信号表明已经有线程进入临界区并拥有此信号<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">HANDLE&nbsp;smphPrint;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;信号量,表示是否已经达到允许的最大线程数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Print(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">str)<br><img id=Codehighlighter1_278_782_Open_Image onclick="this.style.display='none'; Codehighlighter1_278_782_Open_Text.style.display='none'; Codehighlighter1_278_782_Closed_Image.style.display='inline'; Codehighlighter1_278_782_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_278_782_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_278_782_Closed_Text.style.display='none'; Codehighlighter1_278_782_Open_Image.style.display='inline'; Codehighlighter1_278_782_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_278_782_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_278_782_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;EnterCriticalSection(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">csPrint);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;进入临界区<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">WaitForSingleObject(evtPrint,&nbsp;INFINITE);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;等待事件有信号<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">WaitForSingleObject(mtxPrint,&nbsp;INFINITE);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;等待互斥量空置（没有线程拥有它）<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">WaitForSingleObject(smphPrint,&nbsp;INFINITE);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;等待对共享资源请求被通过&nbsp;等于&nbsp;P操作&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">str&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;str</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_543_580_Open_Image onclick="this.style.display='none'; Codehighlighter1_543_580_Open_Text.style.display='none'; Codehighlighter1_543_580_Closed_Image.style.display='inline'; Codehighlighter1_543_580_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_543_580_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_543_580_Closed_Text.style.display='none'; Codehighlighter1_543_580_Open_Image.style.display='inline'; Codehighlighter1_543_580_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_543_580_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_543_580_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%c</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">str);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;LeaveCriticalSection(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">csPrint);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;退出临界区<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">SetEvent(evtPrint);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;把事件信号量恢复,变为有信号<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">ReleaseMutex(mtxPrint);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;释放对互斥量的占有<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">ReleaseSemaphore(smphPrint,&nbsp;1,&nbsp;NULL);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;释放共享资源&nbsp;等于&nbsp;V操作&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ThreadProcess()<br><img id=Codehighlighter1_806_907_Open_Image onclick="this.style.display='none'; Codehighlighter1_806_907_Open_Text.style.display='none'; Codehighlighter1_806_907_Closed_Image.style.display='inline'; Codehighlighter1_806_907_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_806_907_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_806_907_Closed_Text.style.display='none'; Codehighlighter1_806_907_Open_Image.style.display='inline'; Codehighlighter1_806_907_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_806_907_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_806_907_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_833_887_Open_Image onclick="this.style.display='none'; Codehighlighter1_833_887_Open_Text.style.display='none'; Codehighlighter1_833_887_Closed_Image.style.display='inline'; Codehighlighter1_833_887_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_833_887_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_833_887_Closed_Text.style.display='none'; Codehighlighter1_833_887_Open_Image.style.display='inline'; Codehighlighter1_833_887_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_833_887_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_833_887_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Sub&nbsp;&nbsp;Thread&nbsp;is&nbsp;running!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_947_1516_Open_Image onclick="this.style.display='none'; Codehighlighter1_947_1516_Open_Text.style.display='none'; Codehighlighter1_947_1516_Closed_Image.style.display='inline'; Codehighlighter1_947_1516_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_947_1516_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_947_1516_Closed_Text.style.display='none'; Codehighlighter1_947_1516_Open_Image.style.display='inline'; Codehighlighter1_947_1516_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_947_1516_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_947_1516_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;ThreadID;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;InitializeCriticalSection(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">csPrint);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;初始化临界区<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">evtPrint&nbsp;=&nbsp;CreateEvent(NULL,&nbsp;FALSE,&nbsp;TRUE,&nbsp;L"PrintEvent");&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;初始化事件<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">mtxPrint&nbsp;=&nbsp;CreateMutex(NULL,&nbsp;FALSE,&nbsp;L"PrintMutex");&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;初始化互斥量<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">smphPrint=&nbsp;CreateSemaphore(NULL,&nbsp;1,&nbsp;1,&nbsp;L"PrintSemaphore");&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;设置信号量1个资源,因此同时只可以有一个线程访问&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hThread</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateThread(NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPTHREAD_START_ROUTINE)ThreadProcess,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ThreadID);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(ThreadData)<br><img id=Codehighlighter1_1382_1450_Open_Image onclick="this.style.display='none'; Codehighlighter1_1382_1450_Open_Text.style.display='none'; Codehighlighter1_1382_1450_Closed_Image.style.display='inline'; Codehighlighter1_1382_1450_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1382_1450_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1382_1450_Closed_Text.style.display='none'; Codehighlighter1_1382_1450_Open_Image.style.display='inline'; Codehighlighter1_1382_1450_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1382_1450_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1382_1450_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;is&nbsp;waiting&nbsp;for&nbsp;Sub&nbsp;Thread!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;Finished!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br>&nbsp;&nbsp;&nbsp;综上所述：当在同一进程中的多线程同步时，临界区是效率最最高，基本不需要什么开销。而内核对象由于要进行用户态和内核态的切换，开销较大，但是内核对象由于可以命名，因此它们同时可以用于进程间的同步。另外，值得一提的是，信号量可以设置允许访问资源的线程或进程个数，而不仅仅是只允许单个线程或进程访问资源。</p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/91045.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-24 15:14 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/24/91045.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程中局部静态变量初始化的陷阱</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/24/91003.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Fri, 24 Jul 2009 02:47:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/24/91003.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/91003.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/24/91003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/91003.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/91003.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; C++当中常常需要一个全局唯一的对象实例，这时候，我们就会想到单件模式。如何实现这一模式？全局变量当然是一个简单可行的方法，然而，这太丑陋。嗯，其实，丑陋倒也罢了，最严重的是它将引诱程序员滥用全局变量，这将导致维护的灾难。</p>
<p>&nbsp;&nbsp;&nbsp; 既然全局变量是可能有害的，那么，我们我们把它隐藏一下，放到某个类当中去，作为类的静态数据成员。这看上去不错，我也这么认为。当我们只是简单的需要一个全局对象时，这很好，而且足够简单。不过，天空中尚有一朵小小的乌云，让我们来看一看它是什么。</p>
<p>&nbsp;&nbsp;&nbsp; 静态成员变量的初始化，和全局对象一样，实际上是在main函数进入后，我们写下的第一行代码之前被执行的。而且，我们知道那个著名的初始化顺序不可靠的问题（跨编译单元）。当我的全局对象是一个复杂对象――这很常见，比如一个环境管理器――它甚至还需要复杂的装配过程，我们需要考虑：构建这个单件的时候，其对象都准备好了吗？如果我们不能确定，那么一个常见的措施是延迟单件对象的构造――把它延迟到全局对象初始化结束以后怎么样？这好像很容易实现：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_34_76_Open_Image onclick="this.style.display='none'; Codehighlighter1_34_76_Open_Text.style.display='none'; Codehighlighter1_34_76_Closed_Image.style.display='inline'; Codehighlighter1_34_76_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_34_76_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_34_76_Closed_Text.style.display='none'; Codehighlighter1_34_76_Open_Image.style.display='inline'; Codehighlighter1_34_76_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">SomeClass&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;SomeClass&nbsp;::instance()</span><span id=Codehighlighter1_34_76_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_34_76_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;SomeClass&nbsp;inst;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">inst;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>不错吧？它不但可以延迟到全局对象初始化之后，甚至可以延迟到有人需要它的时候，才被构造出来，随需应变，呵呵，是不是很帅？嗯，还有一点小问题，不仅存在对象初始化顺序问题，析构也同样存在问题。局部静态变量的析构，和全局对象一样，是在main函数退出前进行的，如果也要考虑顺序问题的话...是不是有点麻烦呢？</p>
<p>&nbsp;&nbsp;&nbsp; 过度设计是一种罪，我是不是考虑的太复杂了？如果压根就不需要考虑析构顺序，这是不是很完美的解决方案？没那么简单！非但不够完美，而且，这里面仍然存在缺陷：当我们运行在多线程环境的时候，静态变量的初始化来实现单件，是不可靠的――直接的说，静态变量有可能初始化多次！在作实验之前，我们现分析一下静态局部变量的实现方式，下面是前面instance实现的伪码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_17_63_Open_Image onclick="this.style.display='none'; Codehighlighter1_17_63_Open_Text.style.display='none'; Codehighlighter1_17_63_Closed_Image.style.display='inline'; Codehighlighter1_17_63_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_17_63_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_17_63_Closed_Text.style.display='none'; Codehighlighter1_17_63_Open_Image.style.display='inline'; Codehighlighter1_17_63_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">initialized)</span><span id=Codehighlighter1_17_63_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_17_63_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;initialized&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">inst)SomeClass;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">inst;</span></div>
<p>每个静态变量都会拥有自己的初始化与否的标志，静态变量初始化并不是一个原子操作，也没有为多线程而设立互斥区（C++语言本身是没有线程概念的），因此，我们要想实现多线程下的单件延迟创建，就不得不解决重复初始化的问题。至于如何实现，实际上这方面的代码很多了。一个显然的方案是设立互斥区，传统的双检测技术可以有效解决这一问题――至少目前的C++是这样，至于最近在csdn看到在Java中双检测失效的文章，我认为应该由Java语言负责。</p>
<p>&nbsp;&nbsp;&nbsp; 其实，局部静态变量可能多次初始化，并不难理解，实践上，也很少出严重的问题――出问题的条件还是挺苛刻的：多线程，不可多次初始化，恰好多个线程同时调用，恰好在if之后发生线程调度。很少出问题，不等于不出问题，特别的，对于广泛使用的应用程序来说，出错概率就不是一点点了。写这篇东西的原因，是今天在公司看到的一段代码，作了标识符替换：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_36_211_Open_Image onclick="this.style.display='none'; Codehighlighter1_36_211_Open_Text.style.display='none'; Codehighlighter1_36_211_Closed_Image.style.display='inline'; Codehighlighter1_36_211_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_36_211_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_36_211_Closed_Text.style.display='none'; Codehighlighter1_36_211_Open_Image.style.display='inline'; Codehighlighter1_36_211_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">SomeClass&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;SomeClass::GetInstance()</span><span id=Codehighlighter1_36_211_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_36_211_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;CLock&nbsp;g_lock;<br><img id=Codehighlighter1_85_188_Open_Image onclick="this.style.display='none'; Codehighlighter1_85_188_Open_Text.style.display='none'; Codehighlighter1_85_188_Closed_Image.style.display='inline'; Codehighlighter1_85_188_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_85_188_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_85_188_Closed_Text.style.display='none'; Codehighlighter1_85_188_Open_Image.style.display='inline'; Codehighlighter1_85_188_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(m_pInstance&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)</span><span id=Codehighlighter1_85_188_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_85_188_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;g_lock.Lock();<br><img id=Codehighlighter1_130_166_Open_Image onclick="this.style.display='none'; Codehighlighter1_130_166_Open_Text.style.display='none'; Codehighlighter1_130_166_Closed_Image.style.display='inline'; Codehighlighter1_130_166_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_130_166_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_130_166_Closed_Text.style.display='none'; Codehighlighter1_130_166_Open_Image.style.display='inline'; Codehighlighter1_130_166_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(m_pInstance&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)</span><span id=Codehighlighter1_130_166_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_130_166_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;m_pInstance&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SomeClass;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;g_lock.Unlock();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_pInstance;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>就这段代码，虽然知道用双检测，且不说Lock/Unlock可以更好的处理，static CLock g_lock根本就是错误。锁本身可能被初始化多次，象这种资源类型的对象，多次构造几乎肯定会出错的。而对于单件模式的实现，我认为，一般而言，Loki:: SingletonHolder会是一个好的选择。</p>
<p>&nbsp;</p>
<p>本文出处：<a href="http://blog.csdn.net/wingfiring/archive/2005/10/09/498242.aspx">http://blog.csdn.net/wingfiring/archive/2005/10/09/498242.aspx</a></p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/91003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-24 10:47 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/24/91003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程编程浅析（2）——线程间通信</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/23/90940.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Thu, 23 Jul 2009 09:18:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/23/90940.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90940.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/23/90940.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90940.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90940.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;上文我们介绍了如何建立一个简单的多线程程序，多线程之间不可避免的需要进行通信。相比于进程间通信来说，线程间通信无疑是相对比较简单的。</p>
<p>&nbsp;&nbsp;&nbsp;首先我们来看看最简单的方法，那就是使用全局变量（静态变量也可以）来进行通信，由于属于同一个进程的各个线程是处于同一个进程空间中的，并且它们共享这个进程的各种资源，因此它们都可以毫无障碍的访问这个进程中的全局变量。当需要有多个线程来访问一个全局变量时，通常我们会在这个全局变量前加上volatile声明，来告诉编译器这个全局变量是易变的，让编译器不要对这个变量进行优化（至于编译器到底有没有按照你的要求来对volatile进行处理这个暂且不理）。</p>
<p>&nbsp;&nbsp;&nbsp;下面贴出一段简单的示例代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ThreadProcess()<br><img id=Codehighlighter1_112_280_Open_Image onclick="this.style.display='none'; Codehighlighter1_112_280_Open_Text.style.display='none'; Codehighlighter1_112_280_Closed_Image.style.display='inline'; Codehighlighter1_112_280_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_112_280_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_112_280_Closed_Text.style.display='none'; Codehighlighter1_112_280_Open_Image.style.display='inline'; Codehighlighter1_112_280_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_112_280_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_112_280_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_139_244_Open_Image onclick="this.style.display='none'; Codehighlighter1_139_244_Open_Text.style.display='none'; Codehighlighter1_139_244_Closed_Image.style.display='inline'; Codehighlighter1_139_244_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_139_244_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_139_244_Closed_Text.style.display='none'; Codehighlighter1_139_244_Open_Image.style.display='inline'; Codehighlighter1_139_244_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_139_244_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_139_244_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Sub&nbsp;&nbsp;Thread&nbsp;Tick&nbsp;%5d!&nbsp;%5d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,(i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">,&nbsp;ThreadData);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Exit&nbsp;Sub&nbsp;Thread!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_320_682_Open_Image onclick="this.style.display='none'; Codehighlighter1_320_682_Open_Text.style.display='none'; Codehighlighter1_320_682_Closed_Image.style.display='inline'; Codehighlighter1_320_682_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_320_682_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_320_682_Closed_Text.style.display='none'; Codehighlighter1_320_682_Open_Image.style.display='inline'; Codehighlighter1_320_682_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_320_682_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_320_682_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;ThreadID;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hThread</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateThread(NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPTHREAD_START_ROUTINE)ThreadProcess,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ThreadID);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_505_608_Open_Image onclick="this.style.display='none'; Codehighlighter1_505_608_Open_Text.style.display='none'; Codehighlighter1_505_608_Closed_Image.style.display='inline'; Codehighlighter1_505_608_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_505_608_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_505_608_Closed_Text.style.display='none'; Codehighlighter1_505_608_Open_Image.style.display='inline'; Codehighlighter1_505_608_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_505_608_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_505_608_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ThreadData&nbsp;</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;Tick&nbsp;%5d!&nbsp;%5d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;(i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">,&nbsp;ThreadData);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;Loop&nbsp;Finished!&nbsp;\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>&nbsp;&nbsp;&nbsp;除了全局变量之外，还有其他的方法，比如利用消息机制等来实现线程间通信。这个就不详细解释了，关于消息机制，详情请看<a id=viewpost1_TitleUrl href="http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html"><font color=#0066aa>Windows消息机制概述</font></a> 。&nbsp;<br><br>&nbsp;&nbsp;&nbsp;下面，关于多线程中的全局变量，我来介绍点有点偏题的东西：<br><strong>线程局部存储（TLS）</strong><br>&nbsp;&nbsp;&nbsp; 进程中的全局变量与函数内定义的静态(static)变量，是各个线程都可以访问的共享变量。在一个线程修改的内存内容，对所有线程都生效。这是一个优点也是一个缺点。说它是优点，线程的数据交换变得非常快捷。说它是缺点，一个线程死掉了，其它线程也性命不保; 多个线程访问共享数据，需要昂贵的同步开销，也容易造成同步相关的BUG。<br>　　如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量（被称为static memory local to a thread 线程局部静态变量），就需要新的机制来实现。这就是TLS。<br>　　线程局部存储在不同的平台有不同的实现，可移植性不太好。　<br>　　方法一：每个线程创建时系统给它分配一个LPVOID指针的数组（叫做TLS数组），这个数组从C编程角度是隐藏着的不能直接访问，需要通过一些C API函数调用访问。首先定义一些DWORD线程全局变量或函数静态变量,准备作为各个线程访问自己的TLS数组的索引变量。一个线程使用TLS时，第一步在线程内调用TlsAlloc()函数，为一个TLS数组索引变量与这个线程的TLS数组的某个槽(slot）关联起来，例如获得一个索引变量：<br>　　global_dwTLSindex=TLSAlloc(); <br>　　注意，此步之后，当前线程实际上访问的是这个TLS数组索引变量的线程内的拷贝版本。也就说，不同线程虽然看起来用的是同名的TLS数组索引变量，但实际上各个线程得到的可能是不同DWORD值。其意义在于，每个使用TLS的线程获得了一个DWORD类型的线程局部静态变量作为TLS数组的索引变量。C/C++原本没有直接定义线程局部静态变量的机制，所以在如此大费周折。<br>　　第二步，为当前线程动态分配一块内存区域（使用LocalAlloc()函数调用），然后把指向这块内存区域的指针放入TLS数组相应的槽中(使用TlsValue()函数调用)。<br>　　第三步，在当前线程的任何函数内，都可以通过TLS数组的索引变量，使用TlsGetValue()函数得到上一步的那块内存区域的指针，然后就可以进行内存区域的读写操作了。这就实现了在一个线程内部这个范围处处可访问的变量。<br>　　最后，如果不再需要上述线程局部静态变量，要动态释放掉这块内存区域(使用LocalFree()函数)，然后从TLS数组中放弃对应的槽(使用TlsFree()函数）。<br>　　方法二：<br>　　直接声明这个变量是各个线程有自己拷贝的线程局部静态变量：<br>　　__declspec( thread ) int var_name; 
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-23 17:18 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/23/90940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程编程浅析（1）——概述</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/23/90904.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Thu, 23 Jul 2009 03:21:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/23/90904.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90904.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/23/90904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90904.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90904.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;线程，是在进程内部又细分的一个执行单元，他们都是由操作系统来进行划分控制的。系统创建好进程后，实际上就启动执行了该进程的主执行线程，主执行线程以函数地址形式，比如说main或WinMain函数，将程序的启动点提供给Windows系统。主执行线程终止了，进程也就随之终止。每一个进程至少有一个主执行线程，它无需由用户去主动创建，是由系统自动创建的。用户根据需要在应用程序中创建其它线程，多个线程并发地运行于同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中，共同使用这些虚拟地址空间、全局变量和系统资源，所以线程间的通讯非常方便，多线程技术的应用也较为广泛。<br>&nbsp;<br>&nbsp;我们要操作线程，就必须依赖于操作系统提供的接口。下面我们来简要介绍一下操作系统提供的跟线程相关的API函数：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">HANDLE&nbsp;CreateThread(LPSECURITY_ATTRIBUTES&nbsp;lpThreadAttributes,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwStackSize,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPTHREAD_START_ROUTINE&nbsp;lpStartAddress,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPVOID&nbsp;lpParameter,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwCreationFlags,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPDWORD&nbsp;lpThreadId);</span></div>
<p>该函数在其调用进程的进程空间里创建一个新的线程，并返回已建线程的句柄，其中各参数说明如下：<br>lpThreadAttributes：指向一个 SECURITY_ATTRIBUTES 结构的指针，该结构决定了线程的安全属性，一般置为 NULL； <br>dwStackSize：指定了线程的堆栈深度，一般都设置为0； <br>lpStartAddress：表示新线程开始执行时代码所在函数的地址，即线程的起始地址。一般情况为(LPTHREAD_START_ROUTINE)ThreadProcess，ThreadProcess 是线程函数名； <br>lpParameter：指定了线程执行时传送给线程的32位参数，即线程函数的参数； <br>dwCreationFlags：控制线程创建的附加标志，可以取两种值。如果该参数为0，线程在被创建后就会立即开始执行；如果该参数为CREATE_SUSPENDED,则系统产生线程后，该线程处于挂起状态，并不马上执行，直至函数ResumeThread被调用； <br>lpThreadId：该参数返回所创建线程的ID； <br>如果创建成功则返回线程的句柄，否则返回NULL。 </p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">DWORD&nbsp;SuspendThread(HANDLE&nbsp;hThread);</span></div>
<p>该函数用于挂起指定的线程，如果函数执行成功，则线程的执行被终止。</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">DWORD&nbsp;ResumeThread(HANDLE&nbsp;hThread);</span></div>
<p>该函数用于结束线程的挂起状态，执行线程。</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">VOID&nbsp;ExitThread(DWORD&nbsp;dwExitCode);</span></div>
<p>该函数用于线程终结自身的执行，主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。<br>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">BOOL&nbsp;TerminateThread(HANDLE&nbsp;hThread,DWORD&nbsp;dwExitCode);</span></div>
<p>一般情况下，线程运行结束之后，线程函数正常返回，但是应用程序可以调用TerminateThread强行终止某一线程的执行。各参数含义如下：<br>hThread：将被终结的线程的句柄； <br>dwExitCode：用于指定线程的退出码。 <br>使用TerminateThread()终止某个线程的执行是不安全的，可能会引起系统不稳定；虽然该函数立即终止线程的执行，但并不释放线程所占用的资源。因此，一般不建议使用该函数。 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">BOOL&nbsp;PostThreadMessage(DWORD&nbsp;idThread,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;UINT&nbsp;Msg,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;WPARAM&nbsp;wParam,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;LPARAM&nbsp;lParam);</span></div>
<p>该函数将一条消息放入到指定线程的消息队列中，并且不等到消息被该线程处理时便返回。<br>idThread：将接收消息的线程的ID； <br>Msg：指定用来发送的消息； <br>wParam：同消息有关的字参数； <br>lParam：同消息有关的长参数； <br>调用该函数时，如果即将接收消息的线程没有创建消息循环，则该函数执行失败。<font style="BACKGROUND-COLOR: #c7edcc"></font></p>
<br>下面我给出一个简单的建立线程的例子：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ThreadProcess()<br><img id=Codehighlighter1_82_207_Open_Image onclick="this.style.display='none'; Codehighlighter1_82_207_Open_Text.style.display='none'; Codehighlighter1_82_207_Closed_Image.style.display='inline'; Codehighlighter1_82_207_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_82_207_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_82_207_Closed_Text.style.display='none'; Codehighlighter1_82_207_Open_Image.style.display='inline'; Codehighlighter1_82_207_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_82_207_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_82_207_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_109_171_Open_Image onclick="this.style.display='none'; Codehighlighter1_109_171_Open_Text.style.display='none'; Codehighlighter1_109_171_Closed_Image.style.display='inline'; Codehighlighter1_109_171_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_109_171_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_109_171_Closed_Text.style.display='none'; Codehighlighter1_109_171_Open_Image.style.display='inline'; Codehighlighter1_109_171_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_109_171_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_109_171_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Sub&nbsp;Thread&nbsp;Tick&nbsp;%d!&nbsp;\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,i</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Exit&nbsp;Sub&nbsp;Thread!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_247_568_Open_Image onclick="this.style.display='none'; Codehighlighter1_247_568_Open_Text.style.display='none'; Codehighlighter1_247_568_Closed_Image.style.display='inline'; Codehighlighter1_247_568_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_247_568_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_247_568_Closed_Text.style.display='none'; Codehighlighter1_247_568_Open_Image.style.display='inline'; Codehighlighter1_247_568_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_247_568_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_247_568_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;ThreadID;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hThread</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateThread(NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPTHREAD_START_ROUTINE)ThreadProcess,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">ThreadID);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_432_494_Open_Image onclick="this.style.display='none'; Codehighlighter1_432_494_Open_Text.style.display='none'; Codehighlighter1_432_494_Closed_Image.style.display='inline'; Codehighlighter1_432_494_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_432_494_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_432_494_Closed_Text.style.display='none'; Codehighlighter1_432_494_Open_Image.style.display='inline'; Codehighlighter1_432_494_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_432_494_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_432_494_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;Tick&nbsp;%d!&nbsp;\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;i</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">600</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Main&nbsp;Thread&nbsp;Loop&nbsp;Finished!&nbsp;\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-23 11:21 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/23/90904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL入门浅析（5）——使用DLL在进程间共享数据</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/21/90734.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Tue, 21 Jul 2009 07:06:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/21/90734.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90734.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/21/90734.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90734.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90734.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在Win16环境中，DLL的全局数据对每个载入它的进程来说都是相同的,因为所有的进程用的都收同一块地址空间；而在Win32环境中，情况却发生了变化，每个进程都有了它自己的地址空间，DLL函数中的代码所创建的任何对象（包括变量）都归调用它的进程所有。当进程在载入DLL时，操作系统自动把DLL地址映射到该进程的私有空间，也就是进程的虚拟地址空间，而且也复制该DLL的全局数据的一份拷贝到该进程空间。（在物理内存中，多进程载入DLL时，DLL的代码段实际上是只加载了一次，只是将物理地址映射到了各个调用它的进程的虚拟地址空间中，而全局数据会在每个进程都分别加载）。也就是说每个进程所拥有的相同的DLL的全局数据，它们的名称相同，但其值却并不一定是相同的，而且是互不干涉的。<br>因此，在Win32环境下要想在多个进程中共享数据，就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来，放置在一个独立的数据段里，并把该段的属性设置为共享。必须给这些变量赋初值，否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。</p>
<p>在DLL的实现文件中添加下列代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#pragma&nbsp;data_seg(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSharedSection</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;声明共享数据段，并命名该数据段</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;SharedData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;必须在定义的同时进行初始化!!!!</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">#pragma&nbsp;data_seg()</span></div>
<p>&nbsp;</p>
<p>&nbsp;在#pragma data_seg("DLLSharedSection")和#pragma data_seg()之间的所有变量将被访问该Dll的所有进程看到和共享。仅定义一个数据段还不能达到共享数据的目的，还要告诉编译器该段的属性，有三种方法可以实现该目的（其效果是相同的），一种方法是在.DEF文件中加入如下语句：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">SETCTIONS<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DLLSharedSection&nbsp;READ&nbsp;WRITE&nbsp;SHARED</span></div>
<p>&nbsp;</p>
<p>另一种方法是在项目设置的链接选项(Project Setting --〉Link)中加入如下语句：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">/</span><span style="COLOR: #000000">SECTION:DLLSharedSection,rws</span></div>
<p>&nbsp;</p>
<p>还有一种就是使用指令：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">#pragma&nbsp;comment(linker,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/section:.DLLSharedSection,rws</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)</span></div>
<p><br>那么这个数据节中的数据可以在所有DLL的实例之间共享了。所有对这些数据的操作都针对同一个实例的，而不是在每个进程的地址空间中都有一份。<br>&nbsp;<br>当进程隐式或显式调用一个动态库里的函数时，系统都要把这个动态库映射到这个进程的虚拟地址空间里。这使得DLL成为进程的一部分，以这个进程的身份执行，使用这个进程的堆栈。</p>
<p>下面来谈一下在具体使用共享数据段时需要注意的一些问题：</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有在共享数据段中的变量，只有在数据段中经过了初始化之后，才会是进程间共享的。如果没有初始化，那么进程间访问该变量则是未定义的。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有的共享变量都要放置在共享数据段中。如何定义很大的数组，那么也会导致很大的DLL。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不要在共享数据段中存放进程相关的信息。Win32中大多数的数据结构和值（比如HANDLE）只在特定的进程上下文中才是有效地。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每个进程都有它自己的地址空间。因此不要在共享数据段中共享指针，指针指向的地址在不同的地址空间中是不一样的。<br>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLL在每个进程中是被映射在不同的虚拟地址空间中的，因此函数指针也是不安全的。<br><br>当然还有其它的方法来进行进程间的数据共享，比如文件内存映射等，这就涉及到通用的进程间通信了，这里就不多讲了。</p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-21 15:06 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/21/90734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Win32应用程序中进程间通信方法分析与比较</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/21/90697.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Tue, 21 Jul 2009 02:32:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/21/90697.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90697.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/21/90697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90697.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90697.html</trackback:ping><description><![CDATA[<p><strong>1</strong> <strong>进程与进程通信</strong></p>
<p>&nbsp;<wbr></p>
<p>　　进程是装入内存并准备执行的程序，每个进程都有私有的虚拟地址空间，由代码、数据以及它可利用的系统资源(如文件、管道等)组成。多进程/多线程是Windows操作系统的一个基本特征。Microsoft Win32应用编程接口(Application Programming Interface, API)提供了大量支持应用程序间数据共享和交换的机制，这些机制行使的活动称为进程间通信(InterProcess Communication, IPC)，进程通信就是指不同进程间进行数据共享和数据交换。<br>　　正因为使用Win32 API进行进程通信方式有多种，如何选择恰当的通信方式就成为应用开发中的一个重要问题，下面本文将对Win32中进程通信的几种方法加以分析和比较。</p>
<p>&nbsp;<wbr></p>
<p><strong>2</strong> <strong>进程通信方法</strong></p>
<p><strong>2.1</strong> <strong>文件映射</strong><br>　　文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待。因此，进程不必使用文件I/O操作，只需简单的指针操作就可读取和修改文件的内容。<br>　　Win32 API允许多个进程访问同一文件映射对象，各个进程在它自己的地址空间里接收内存的指针。通过使用这些指针，不同进程就可以读或修改文件的内容，实现了对文件中数据的共享。<br>　　应用程序有三种方法来使多个进程共享一个文件映射对象。<br>　　(1)继承：第一个进程建立文件映射对象，它的子进程继承该对象的句柄。<br>　　(2)命名文件映射：第一个进程在建立文件映射对象时可以给该对象指定一个名字(可与文件名不同)。第二个进程可通过这个名字打开此文件映射对象。另外，第一个进程也可以通过一些其它IPC机制(有名管道、邮件槽等)把名字传给第二个进程。<br>　　(3)句柄复制：第一个进程建立文件映射对象，然后通过其它IPC机制(有名管道、邮件槽等)把对象句柄传递给第二个进程。第二个进程复制该句柄就取得对该文件映射对象的访问权限。<br>　　文件映射是在多个进程间共享数据的非常有效方法，有较好的安全性。但文件映射只能用于本地机器的进程之间，不能用于网络中，而开发者还必须控制进程间的同步。<br><strong>2.2</strong> <strong>共享内存</strong><br>　　Win32 API中共享内存(Shared Memory)实际就是文件映射的一种特殊情况。进程在创建文件映射对象时用0xFFFFFFFF来代替文件句柄(HANDLE)，就表示了对应的文件映射对象是从操作系统页面文件访问内存，其它进程打开该文件映射对象就可以访问该内存块。由于共享内存是用文件映射实现的，所以它也有较好的安全性，也只能运行于同一计算机上的进程之间。<br><strong>2.3</strong> <strong>匿名管道</strong><br>　　管道(Pipe)是一种具有两个端点的通信通道：有一端句柄的进程可以和有另一端句柄的进程通信。管道可以是单向－一端是只读的，另一端点是只写的；也可以是双向的一管道的两端点既可读也可写。<br>　　匿名管道(Anonymous Pipe)是在父进程和子进程之间，或同一父进程的两个子进程之间传输数据的无名字的单向管道。通常由父进程创建管道，然后由要通信的子进程继承通道的读端点句柄或写端点句柄，然后实现通信。父进程还可以建立两个或更多个继承匿名管道读和写句柄的子进程。这些子进程可以使用管道直接通信，不需要通过父进程。<br>　　匿名管道是单机上实现子进程标准I/O重定向的有效方法，它不能在网上使用，也不能用于两个不相关的进程之间。<br><strong>2.4</strong> <strong>命名管道</strong><br>　　命名管道(Named Pipe)是服务器进程和一个或多个客户进程之间通信的单向或双向管道。不同于匿名管道的是命名管道可以在不相关的进程之间和不同计算机之间使用，服务器建立命名管道时给它指定一个名字，任何进程都可以通过该名字打开管道的另一端，根据给定的权限和服务器进程通信。<br>　　命名管道提供了相对简单的编程接口，使通过网络传输数据并不比同一计算机上两进程之间通信更困难，不过如果要同时和多个进程通信它就力不从心了。<br><strong>2.5</strong> <strong>邮件槽</strong><br>　　邮件槽(Mailslots)提供进程间单向通信能力，任何进程都能建立邮件槽成为邮件槽服务器。其它进程，称为邮件槽客户，可以通过邮件槽的名字给邮件槽服务器进程发送消息。进来的消息一直放在邮件槽中，直到服务器进程读取它为止。一个进程既可以是邮件槽服务器也可以是邮件槽客户，因此可建立多个邮件槽实现进程间的双向通信。<br>　　通过邮件槽可以给本地计算机上的邮件槽、其它计算机上的邮件槽或指定网络区域中所有计算机上有同样名字的邮件槽发送消息。广播通信的消息长度不能超过400字节，非广播消息的长度则受邮件槽服务器指定的最大消息长度的限制。<br>　　邮件槽与命名管道相似，不过它传输数据是通过不可靠的数据报(如TCP/IP协议中的UDP包)完成的，一旦网络发生错误则无法保证消息正确地接收，而命名管道传输数据则是建立在可靠连接基础上的。不过邮件槽有简化的编程接口和给指定网络区域内的所有计算机广播消息的能力，所以邮件槽不失为应用程序发送和接收消息的另一种选择。<br><strong>2.6</strong> <strong>剪贴板</strong><br>　　剪贴板(Clipped Board)实质是Win32 API中一组用来传输数据的函数和消息，为Windows应用程序之间进行数据共享提供了一个中介，Windows已建立的剪切(复制)－粘贴的机制为不同应用程序之间共享不同格式数据提供了一条捷径。当用户在应用程序中执行剪切或复制操作时，应用程序把选取的数据用一种或多种格式放在剪贴板上。然后任何其它应用程序都可以从剪贴板上拾取数据，从给定格式中选择适合自己的格式。<br>　　剪贴板是一个非常松散的交换媒介，可以支持任何数据格式，每一格式由一无符号整数标识，对标准(预定义)剪贴板格式，该值是Win32 API定义的常量；对非标准格式可以使用Register Clipboard Format函数注册为新的剪贴板格式。利用剪贴板进行交换的数据只需在数据格式上一致或都可以转化为某种格式就行。但剪贴板只能在基于Windows的程序中使用，不能在网络上使用。<br><strong>2.7</strong> <strong>动态数据交换</strong><br>　　动态数据交换(DDE)是使用共享内存在应用程序之间进行数据交换的一种进程间通信形式。应用程序可以使用DDE进行一次性数据传输，也可以当出现新数据时，通过发送更新值在应用程序间动态交换数据。<br>　　DDE和剪贴板一样既支持标准数据格式(如文本、位图等)，又可以支持自己定义的数据格式。但它们的数据传输机制却不同，一个明显区别是剪贴板操作几乎总是用作对用户指定操作的一次性应答－如从菜单中选择Paste命令。尽管DDE也可以由用户启动，但它继续发挥作用一般不必用户进一步干预。DDE有三种数据交换方式：<br>　　(1) 冷链：数据交换是一次性数据传输，与剪贴板相同。<br>　　(2) 温链：当数据交换时服务器通知客户，然后客户必须请求新的数据。<br>　　(3) 热链：当数据交换时服务器自动给客户发送数据。<br>　　DDE交换可以发生在单机或网络中不同计算机的应用程序之间。开发者还可以定义定制的DDE数据格式进行应用程序之间特别目的IPC，它们有更紧密耦合的通信要求。大多数基于Windows的应用程序都支持DDE。<br><strong>2.8</strong> <strong>对象连接与嵌入</strong><br>　　应用程序利用对象连接与嵌入(OLE)技术管理复合文档(由多种数据格式组成的文档)，OLE提供使某应用程序更容易调用其它应用程序进行数据编辑的服务。例如，OLE支持的字处理器可以嵌套电子表格，当用户要编辑电子表格时OLE库可自动启动电子表格编辑器。当用户退出电子表格编辑器时，该表格已在原始字处理器文档中得到更新。在这里电子表格编辑器变成了字处理器的扩展，而如果使用DDE，用户要显式地启动电子表格编辑器。<br>　　同DDE技术相同，大多数基于Windows的应用程序都支持OLE技术。<br><strong>2.9</strong> <strong>动态连接库</strong><br>　　Win32动态连接库(DLL)中的全局数据通过特殊方法可以被调用DLL的所有进程共享，这就又给进程间通信开辟了一条新的途径，当然访问时要注意同步问题。<br>　　虽然可以通过DLL进行进程间数据共享，但从数据安全的角度考虑，我们并不提倡这种方法，使用带有访问权限控制的共享内存的方法更好一些。<br><strong>2.10</strong> <strong>远程过程调用</strong><br>　　Win32 API提供的远程过程调用(RPC)使应用程序可以使用远程调用函数，这使在网络上用RPC进行进程通信就像函数调用那样简单。RPC既可以在单机不同进程间使用也可以在网络中使用。<br>　　由于Win32 API提供的RPC服从OSF-DCE(Open Software Foundation Distributed Computing Environment)标准。所以通过Win32 API编写的RPC应用程序能与其它操作系统上支持DEC的RPC应用程序通信。使用RPC开发者可以建立高性能、紧密耦合的分布式应用程序。<br><strong>2.11 NetBios</strong><strong>函数</strong><br>　　Win32 API提供NetBios函数用于处理低级网络控制，这主要是为IBM NetBios系统编写与Windows的接口。除非那些有特殊低级网络功能要求的应用程序，其它应用程序最好不要使用NetBios函数来进行进程间通信。<br><strong>2.12 Sockets</strong><br>　　Windows Sockets规范是以U.C.Berkeley大学BSD UNIX中流行的Socket接口为范例定义的一套Windows下的网络编程接口。除了Berkeley Socket原有的库函数以外，还扩展了一组针对Windows的函数，使程序员可以充分利用Windows的消息机制进行编程。<br>　　现在通过Sockets实现进程通信的网络应用越来越多，这主要的原因是Sockets的跨平台性要比其它IPC机制好得多，另外WinSock 2.0不仅支持TCP/IP协议，而且还支持其它协议(如IPX)。Sockets的唯一缺点是它支持的是底层通信操作，这使得在单机的进程间进行简单数据传递不太方便，这时使用下面将介绍的WM_COPYDATA消息将更合适些。<br><strong>2.13 WM_COPYDATA</strong><strong>消息</strong><br>　　WM_COPYDATA是一种非常强大却鲜为人知的消息。当一个应用向另一个应用传送数据时，发送方只需使用调用SendMessage函数，参数是目的窗口的句柄、传递数据的起始地址、WM_COPYDATA消息。接收方只需像处理其它消息那样处理WM_COPY DATA消息，这样收发双方就实现了数据共享。<br>　　WM_COPYDATA是一种非常简单的方法，它在底层实际上是通过文件映射来实现的。它的缺点是灵活性不高，并且它只能用于Windows平台的单机环境下。</p>
<p>&nbsp;<wbr></p>
<p><strong>3</strong> <strong>结束语</strong></p>
<p>　　Win32 API为应用程序实现进程间通信提供了如此多种选择方案，那么开发者如何进行选择呢？通常在决定使用哪种IPC方法之前应考虑下一些问题，如应用程序是在网络环境下还是在单机环境下工作等。<br></p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-21 10:32 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/21/90697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL入门浅析（4）——从DLL中导出类</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90663.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Mon, 20 Jul 2009 12:50:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90663.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90663.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90663.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90663.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90663.html</trackback:ping><description><![CDATA[&nbsp;前面介绍了怎么从DLL中导出函数和变量，实际上导出类的方法也是大同小异，废话就不多说了，下面给个简单例子示范一下，也就不多做解释了。<br><br>DLL头文件：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#ifndef&nbsp;_DLL_SAMPLE_H<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;_DLL_SAMPLE_H</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;通过宏来控制是导入还是导出</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">#ifdef&nbsp;_DLL_SAMPLE<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API&nbsp;__declspec(dllexport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API&nbsp;__declspec(dllimport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;导出/导入变量声明</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">DLL_SAMPLE_API&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;DLLClass<br><img id=Codehighlighter1_228_257_Open_Image onclick="this.style.display='none'; Codehighlighter1_228_257_Open_Text.style.display='none'; Codehighlighter1_228_257_Closed_Image.style.display='inline'; Codehighlighter1_228_257_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_228_257_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_228_257_Closed_Text.style.display='none'; Codehighlighter1_228_257_Open_Image.style.display='inline'; Codehighlighter1_228_257_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_228_257_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_228_257_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Show();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#undef</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>DLL实现文件：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#define&nbsp;_DLL_SAMPLE<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#ifndef&nbsp;_DLL_SAMPLE_H<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#endif<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">APIENTRY声明DLL函数入口点</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">BOOL&nbsp;APIENTRY&nbsp;DllMain(HANDLE&nbsp;hModule,&nbsp;DWORD&nbsp;ul_reason_for_call,&nbsp;LPVOID&nbsp;lpReserved)<br><img id=Codehighlighter1_218_385_Open_Image onclick="this.style.display='none'; Codehighlighter1_218_385_Open_Text.style.display='none'; Codehighlighter1_218_385_Closed_Image.style.display='inline'; Codehighlighter1_218_385_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_218_385_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_218_385_Closed_Text.style.display='none'; Codehighlighter1_218_385_Open_Image.style.display='inline'; Codehighlighter1_218_385_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_218_385_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_218_385_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">&nbsp;(ul_reason_for_call)<br><img id=Codehighlighter1_250_369_Open_Image onclick="this.style.display='none'; Codehighlighter1_250_369_Open_Text.style.display='none'; Codehighlighter1_250_369_Closed_Image.style.display='inline'; Codehighlighter1_250_369_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_250_369_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_250_369_Closed_Text.style.display='none'; Codehighlighter1_250_369_Open_Image.style.display='inline'; Codehighlighter1_250_369_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>　</span><span id=Codehighlighter1_250_369_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_250_369_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_ATTACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_ATTACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_DETACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_DETACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>　}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DLLClass::Show()<br><img id=Codehighlighter1_410_440_Open_Image onclick="this.style.display='none'; Codehighlighter1_410_440_Open_Text.style.display='none'; Codehighlighter1_410_440_Closed_Image.style.display='inline'; Codehighlighter1_410_440_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_410_440_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_410_440_Closed_Text.style.display='none'; Codehighlighter1_410_440_Open_Image.style.display='inline'; Codehighlighter1_410_440_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_410_440_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_410_440_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLClass&nbsp;show!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>应用程序调用DLL
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#pragma&nbsp;comment(lib,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[])<br><img id=Codehighlighter1_96_136_Open_Image onclick="this.style.display='none'; Codehighlighter1_96_136_Open_Text.style.display='none'; Codehighlighter1_96_136_Closed_Image.style.display='inline'; Codehighlighter1_96_136_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_96_136_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_96_136_Closed_Text.style.display='none'; Codehighlighter1_96_136_Open_Image.style.display='inline'; Codehighlighter1_96_136_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_96_136_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_96_136_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　DLLClass&nbsp;dc;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;dc.Show();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>大家可能发现了，上面我没有使用模块定义文件（.def）声明导出类也没有用显式链接导入DLL。 <br>用Depends查看前面编译出来的DLL文件，会发现里面导出了很奇怪的symbol，这是因为C++编译器在编译时会对symbol进行修饰。<br>这是我从别人那儿转来的截图。</p>
<p><img height=160 alt="" src="http://www.cppblog.com/images/cppblog_com/suiaiguo/85DF01C9E3E7ECB0E9B1E2C262F88F76.jpg" width=483 border=0><br><br>网上找了下，发现了C++编译时函数名的修饰约定规则</p>
<p>__stdcall调用约定：</p>
<p>1、以"?"标识函数名的开始，后跟函数名；<br>2、函数名后面以"@@YG"标识参数表的开始，后跟参数表；<br>3、参数表以代号表示：</p>
<p>X——void，<br>D——char，<br>E——unsigned char，<br>F——short，<br>H——int，<br>I——unsigned int，<br>J——long，<br>K——unsigned long，<br>M——float，<br>N——double，<br>_N——bool，<br>....</p>
<p>　　PA——表示指针，后面的代号表明指针类型，如果相同类型的指针连续出现，以"0"代替，一个"0"代表一次重复；<br>4、参数表的第一项为该函数的返回值类型，其后依次为参数的数据类型,指针标识在其所指数据类型前； <br>5、参数表后以"@Z"标识整个名字的结束，如果该函数无参数，则以"Z"标识结束。<br>　　其格式为"?functionname@@YG*****@Z"或<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#64;&#89;&#71;&#42;&#88;&#90;">?functionname@@YG*XZ</a>，</p>
<pre>    int Test1（char *var1,unsigned long）<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#45;&#45;&#45;&#45;&#45;&#8220;&#63;&#84;&#101;&#115;&#116;&#49;&#64;&#64;&#89;&#71;&#72;&#80;&#65;&#68;&#75;&#64;&#90;&#8221;">-----&#8220;?Test1@@YGHPADK@Z&#8221;
</a>     void Test2（）                          -----&#8220;?Test2@@YGXXZ&#8221;
</pre>
<p>__cdecl调用约定：<br>　　规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YA"。</p>
<p>__fastcall调用约定：<br>　　规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YI"。<br><br>VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用。<br><br>虽然因为C++编译器对symbol进行修饰的原因不能直接用def文件声明导出类和显式链接，但是可以用另外一种取巧的方式。</p>
在头文件中类的声明中添加一个友元函数：<br>friend DLLClass* CreatDLLClass();<br>然后声明CreatDLLClass()为导出函数，通过调用该函数返回一个DLLClass类的对象，同样达到了导出类的目的。<br>这样，就可以用显式链接来调用CreatDLLClass()，从而得到类对象了。
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90663.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-20 20:50 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/20/90663.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL入门浅析（3）——从DLL中导出变量</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90643.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Mon, 20 Jul 2009 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90643.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90643.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90643.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90643.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90643.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp; 前面介绍了怎么从DLL中导出函数，下面我们来看一下如何从DLL中导出变量来。</p>
<p>&nbsp;&nbsp; 声明为导出变量时，同样有两种方法：<br>&nbsp;&nbsp; 第一种是用__declspec进行导出声明</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#ifndef&nbsp;_DLL_SAMPLE_H<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;_DLL_SAMPLE_H</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;如果定义了C++编译器，那么声明为C链接方式</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">#ifdef&nbsp;__cplusplus<br><img id=Codehighlighter1_101_342_Open_Image onclick="this.style.display='none'; Codehighlighter1_101_342_Open_Text.style.display='none'; Codehighlighter1_101_342_Closed_Image.style.display='inline'; Codehighlighter1_101_342_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_101_342_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_101_342_Closed_Text.style.display='none'; Codehighlighter1_101_342_Open_Image.style.display='inline'; Codehighlighter1_101_342_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_101_342_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_101_342_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;通过宏来控制是导入还是导出</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">#ifdef&nbsp;_DLL_SAMPLE<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API&nbsp;__declspec(dllexport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API&nbsp;__declspec(dllimport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;导出/导入变量声明</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">DLL_SAMPLE_API&nbsp;</span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;DLLData;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#undef</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;__cplusplus<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>&nbsp; 第二种是用模块定义文件（.def）进行导出声明</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">LIBRARY&nbsp;DLLSample<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DESCRIPTION&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">my&nbsp;simple&nbsp;DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>EXPORTS<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DLLData&nbsp;DATA&nbsp;&nbsp;；DATA表示这是数据（变量）</span></div>
<p>&#160;</p>
&nbsp;&nbsp;&nbsp;下面是DLL的实现文件
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;_DLL_SAMPLE</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#ifndef&nbsp;_DLL_SAMPLE_H<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;DLLData;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">APIENTRY声明DLL函数入口点</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">BOOL&nbsp;APIENTRY&nbsp;DllMain(HANDLE&nbsp;hModule,&nbsp;DWORD&nbsp;ul_reason_for_call,&nbsp;LPVOID&nbsp;lpReserved)<br><img id=Codehighlighter1_232_451_Open_Image onclick="this.style.display='none'; Codehighlighter1_232_451_Open_Text.style.display='none'; Codehighlighter1_232_451_Closed_Image.style.display='inline'; Codehighlighter1_232_451_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_232_451_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_232_451_Closed_Text.style.display='none'; Codehighlighter1_232_451_Open_Image.style.display='inline'; Codehighlighter1_232_451_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_232_451_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_232_451_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">&nbsp;(ul_reason_for_call)<br><img id=Codehighlighter1_264_435_Open_Image onclick="this.style.display='none'; Codehighlighter1_264_435_Open_Text.style.display='none'; Codehighlighter1_264_435_Closed_Image.style.display='inline'; Codehighlighter1_264_435_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_264_435_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_264_435_Closed_Text.style.display='none'; Codehighlighter1_264_435_Open_Image.style.display='inline'; Codehighlighter1_264_435_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>　</span><span id=Codehighlighter1_264_435_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_264_435_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_ATTACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DLLData&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;在入口函数中对变量进行初始化</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_ATTACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_DETACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_DETACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>　}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>同样，应用程序调用DLL中的变量也有两种方法。<br>第一种是隐式链接：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#pragma&nbsp;comment(lib,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[])<br><img id=Codehighlighter1_115_155_Open_Image onclick="this.style.display='none'; Codehighlighter1_115_155_Open_Text.style.display='none'; Codehighlighter1_115_155_Closed_Image.style.display='inline'; Codehighlighter1_115_155_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_115_155_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_115_155_Closed_Text.style.display='none'; Codehighlighter1_115_155_Open_Image.style.display='inline'; Codehighlighter1_115_155_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_115_155_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_115_155_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;DLLSample);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;<br>第二种是显式链接：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_53_484_Open_Image onclick="this.style.display='none'; Codehighlighter1_53_484_Open_Text.style.display='none'; Codehighlighter1_53_484_Closed_Image.style.display='inline'; Codehighlighter1_53_484_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_53_484_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_53_484_Closed_Text.style.display='none'; Codehighlighter1_53_484_Open_Image.style.display='inline'; Codehighlighter1_53_484_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_53_484_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_53_484_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;my_int;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hInstLibrary&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;LoadLibrary(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.dll</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hInstLibrary&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)<br><img id=Codehighlighter1_181_227_Open_Image onclick="this.style.display='none'; Codehighlighter1_181_227_Open_Text.style.display='none'; Codehighlighter1_181_227_Closed_Image.style.display='inline'; Codehighlighter1_181_227_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_181_227_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_181_227_Closed_Text.style.display='none'; Codehighlighter1_181_227_Open_Image.style.display='inline'; Codehighlighter1_181_227_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_181_227_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_181_227_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInstLibrary);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my_int&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)GetProcAddress(hInstLibrary,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLData</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(dllFunc&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)<br><img id=Codehighlighter1_331_377_Open_Image onclick="this.style.display='none'; Codehighlighter1_331_377_Open_Text.style.display='none'; Codehighlighter1_331_377_Closed_Image.style.display='inline'; Codehighlighter1_331_377_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_331_377_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_331_377_Closed_Text.style.display='none'; Codehighlighter1_331_377_Open_Image.style.display='inline'; Codehighlighter1_331_377_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_331_377_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_331_377_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInstLibrary);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">my_int;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cin.</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInstLibrary);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>通过GetProcAddress取出的函数或者变量都是地址，因此，需要解引用并且转类型。</p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-20 17:37 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/20/90643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL入门浅析（2）——如何使用DLL</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90621.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Mon, 20 Jul 2009 06:27:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90621.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90621.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90621.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90621.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90621.html</trackback:ping><description><![CDATA[<p>上文我简单的介绍了如何建立一个简单DLL，下面再我简单的介绍一下如何使用一个DLL。当一个DLL被生成后，它创建了一个.dll文件和一个.lib文件；这两个都是你需要的。要使用DLL，就需要载入这个DLL。</p>
<p><strong>隐式链接</strong></p>
<p>这里有两个方法来载入一个DLL；一个方法是捷径另一个则相比要复杂些。捷径是只链接到你.lib 文件并将.dll文件置入你的新项目的路径中去。因此，创建一个新的空的Win32控制台项目并添加一个源文件。将你做的DLL放入你的新项目相同的目录下。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#pragma&nbsp;comment(lib,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">你也可以在项目属性中设置库的链接</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_113_156_Open_Image onclick="this.style.display='none'; Codehighlighter1_113_156_Open_Text.style.display='none'; Codehighlighter1_113_156_Closed_Image.style.display='inline'; Codehighlighter1_113_156_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_113_156_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_113_156_Closed_Text.style.display='none'; Codehighlighter1_113_156_Open_Image.style.display='inline'; Codehighlighter1_113_156_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_113_156_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_113_156_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestDLL(</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>这就是载入一个DLL的简单方法。</p>
<p><strong>显式链接</strong> </p>
<p>难点的加载DLL的方法稍微有点复杂。你将需要函数指针和一些Windows函数。但是，通过这种载入DLLs的方法，你不需要DLL的.lib或头文件，而只需要DLL。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">DLLFunc)(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_82_516_Open_Image onclick="this.style.display='none'; Codehighlighter1_82_516_Open_Text.style.display='none'; Codehighlighter1_82_516_Closed_Image.style.display='inline'; Codehighlighter1_82_516_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_82_516_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_82_516_Closed_Text.style.display='none'; Codehighlighter1_82_516_Open_Image.style.display='inline'; Codehighlighter1_82_516_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_82_516_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_82_516_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DLLFunc&nbsp;dllFunc;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hInstLibrary&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;LoadLibrary(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.dll</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hInstLibrary&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)<br><img id=Codehighlighter1_215_261_Open_Image onclick="this.style.display='none'; Codehighlighter1_215_261_Open_Text.style.display='none'; Codehighlighter1_215_261_Closed_Image.style.display='inline'; Codehighlighter1_215_261_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_215_261_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_215_261_Closed_Text.style.display='none'; Codehighlighter1_215_261_Open_Image.style.display='inline'; Codehighlighter1_215_261_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_215_261_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_215_261_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInstLibrary);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dllFunc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(DLLFunc)GetProcAddress(hInstLibrary,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">TestDLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(dllFunc&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)<br><img id=Codehighlighter1_368_414_Open_Image onclick="this.style.display='none'; Codehighlighter1_368_414_Open_Text.style.display='none'; Codehighlighter1_368_414_Closed_Image.style.display='inline'; Codehighlighter1_368_414_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_368_414_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_368_414_Closed_Text.style.display='none'; Codehighlighter1_368_414_Open_Image.style.display='inline'; Codehighlighter1_368_414_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_368_414_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_368_414_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInstLibrary);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dllFunc(</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cin.</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLibrary(hInstLibrary);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>首先你会注意到：这里包括进了文件&#8220;windows.h&#8221;同时移走了&#8220;DLLSample.h&#8221;。原因很简单：因为windows.h包含了一些Windows函数，当然你现在将只需要其中几个而已。它也包含了一些将会用到的Windows特定变量。你可以去掉DLL的头文件（DLLSample.h）因为－如我前面所说－当你使用这个方法载入DLL时你并不需要它。</p>
<p>下面你会看到：下面的一句代码:</p>
<p>typedef void (*DLLFunc)(int);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>这是一个函数指针类型的定义。指向一个函数是一个int型的参数，返回值为void类型。</p>
<p>一个HINSTANCE是一个Windows数据类型：是一个实例的句柄；在此情况下，这个实例将是这个DLL。你可以通过使用函数LoadLibrary()获得DLL的实例，它获得一个名称作为参数。在调用LoadLibrary函数后，你必需查看一下函数返回是否成功。你可以通过检查HINSTANCE是否等于NULL（在Windows.h中定义为0或Windows.h包含的一个头文件）来查看其是否成功。如果其等于NULL，该句柄将是无效的，并且你必需释放这个库。换句话说，你必需释放DLL获得的内存。如果函数返回成功，你的HINSTANCE就包含了指向DLL的句柄。</p>
<p>一旦你获得了指向DLL的句柄，你现在可以从DLL中重新获得函数。为了这样作，你必须使用函数GetProcAddress()，它将DLL的句柄（你可以使用HINSTANCE）和函数的名称作为参数。你可以让函数指针获得由GetProcAddress()返回的值，同时你必需将GetProcAddress()转换为那个函数定义的函数指针。举个例子，对于Add()函数，你必需将GetProcAddress()转换为AddFunc；这就是它知道参数及返回值的原因。现在，最好先确定函数指针是否等于NULL以及它们拥有DLL的函数。这只是一个简单的if语句；如果其中一个等于NULL，你必需如前所述释放库。</p>
<p>一旦函数指针拥有DLL的函数，你现在就可以使用它们了，但是这里有一个需要注意的地方：你不能使用函数的实际名称；你必需使用函数指针来调用它们。在那以后，所有你需要做的是释放库如此而已。</p>
<p><strong>模块句柄</strong></p>
<p>进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识。进程自己还有一个HINSTANCE句柄。所有这些模块句柄都只有在特定的进程内部有效，它们代表了DLL或EXE模块在进程虚拟空间中的起始地址。在Win32中，HINSTANCE和HMODULE的值是相同的，这个两种类型可以替换使用。进程模块句柄几乎总是等于0x400000，而DLL模块的加载地址的缺省句柄是0x10000000。如果程序同时使用了几个DLL模块，每一个都会有不同的HINSTANCE值。这是因为在创建DLL文件时指定了不同的基地址，或者是因为加载程序对DLL代码进行了重定位。<br>模块句柄对于加载资源特别重要。Win32 的FindResource函数中带有一个HINSTANCE参数。EXE和DLL都有其自己的资源。如果应用程序需要来自于DLL的资源，就将此参数指定为DLL的模块句柄。如果需要EXE文件中包含的资源，就指定EXE的模块句柄。<br>但是在使用这些句柄之前存在一个问题，你怎样得到它们呢？如果需要得到EXE模块句柄，调用带有Null参数的Win32函数GetModuleHandle；如果需要DLL模块句柄，就调用以DLL文件名为参数的Win32函数GetModuleHandle。</p>
<p><strong>应用程序怎样找到DLL文件</strong></p>
<p>如果应用程序使用LoadLibrary显式链接，那么在这个函数的参数中可以指定DLL文件的完整路径。如果不指定路径，或是进行隐式链接，Windows将遵循下面的搜索顺序来定位DLL：<br>1． 包含EXE文件的目录，<br>2． 进程的当前工作目录，<br>3． Windows系统目录，<br>4． Windows目录，<br>5． 列在Path环境变量中的一系列目录。<br>这里有一个很容易发生错误的陷阱。如果你使用VC＋＋进行项目开发，并且为DLL模块专门创建了一个项目，然后将生成的DLL文件拷贝到系统目录下，从应用程序中调用DLL模块。到目前为止，一切正常。接下来对DLL模块做了一些修改后重新生成了新的DLL文件，但你忘记将新的DLL文件拷贝到系统目录下。下一次当你运行应用程序时，它仍加载了老版本的DLL文件，这可要当心！</p>
<p><strong>调试DLL程序</strong></p>
<p>Microsoft 的VC＋＋是开发和测试DLL的有效工具，只需从DLL项目中运行调试程序即可。当你第一次这样操作时，调试程序会向你询问EXE文件的路径。此后每次在调试程序中运行DLL时，调试程序会自动加载该EXE文件。然后该EXE文件用上面的搜索序列发现DLL文件，这意味着你必须设置Path环境变量让其包含DLL文件的磁盘路径，或者也可以将DLL文件拷贝到搜索序列中的目录路径下。<br>或者当你调试EXE程序时，在Project Setting中，将Debug选项卡中的Category设置为Additional DLLs。就可以同时调试EXE和它调用的DLL（当然，你需要有DLL的源代码）了。<br>&nbsp;&nbsp;&nbsp;<br></p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-20 14:27 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/20/90621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL入门浅析（1）——如何建立DLL</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90619.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Mon, 20 Jul 2009 05:49:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90619.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90619.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/20/90619.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90619.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90619.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;初学DLL，结合教程，总结一下自己的所得，希望对DLL初学者们有所帮助。<br><br>&nbsp;&nbsp;&nbsp;动态链接库（DLL）是从C语言函数库和Pascal库单元的概念发展而来的。所有的C语言标准库函数都存放在某一函数库中。在链接应用程序的过程中，链接器从库文件中拷贝程序调用的函数代码，并把这些函数代码添加到可执行文件中。这种方法同只把函数储存在已编译的OBJ文件中相比更有利于代码的重用。但随着Windows这样的多任务环境的出现，函数库的方法显得过于累赘。如果为了完成屏幕输出、消息处理、内存管理、对话框等操作，每个程序都不得不拥有自己的函数，那么Windows程序将变得非常庞大。Windows的发展要求允许同时运行的几个程序共享一组函数的单一拷贝。动态链接库就是在这种情况下出现的。动态链接库不用重复编译或链接，一旦装入内存，DLL函数可以被系统中的任何正在运行的应用程序软件所使用，而不必再将DLL函数的另一拷贝装入内存。<br><br>&nbsp;&nbsp;&nbsp;下面我们一步一步来建立一个DLL。<br><br>&nbsp;&nbsp;&nbsp;一、建立一个DLL工程<br>&nbsp;&nbsp;&nbsp;新建一个工程，选择Win32 控制台项目（Win32 Console Application），并且在应用程序设置标签（the advanced tab）上，选择DLL和空项目选项。<br><br>&nbsp;&nbsp;&nbsp;二、声明导出函数<br>&nbsp;&nbsp;&nbsp;这里有两种方法声明导出函数：一种是通过使用__declspec(dllexport)，添加到需要导出的函数前，进行声明；另外一种就是通过模块定义文件（Module-Definition File即.DEF）来进行声明。<br>&nbsp;&nbsp;&nbsp;第一种方法，建立头文件DLLSample.h，在头文件中，对需要导出的函数进行声明。
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#ifndef&nbsp;_DLL_SAMPLE_H<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;_DLL_SAMPLE_H</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;如果定义了C++编译器，那么声明为C链接方式</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">#ifdef&nbsp;__cplusplus<br><img id=Codehighlighter1_101_341_Open_Image onclick="this.style.display='none'; Codehighlighter1_101_341_Open_Text.style.display='none'; Codehighlighter1_101_341_Closed_Image.style.display='inline'; Codehighlighter1_101_341_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_101_341_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_101_341_Closed_Text.style.display='none'; Codehighlighter1_101_341_Open_Image.style.display='inline'; Codehighlighter1_101_341_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">extern</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_101_341_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_101_341_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;通过宏来控制是导入还是导出</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">#ifdef&nbsp;_DLL_SAMPLE<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API&nbsp;__declspec(dllexport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API&nbsp;__declspec(dllimport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;导出/导入函数声明</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">DLL_SAMPLE_API&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TestDLL(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">#undef</span><span style="COLOR: #000000">&nbsp;DLL_SAMPLE_API</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;__cplusplus<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>&nbsp;&nbsp;&nbsp;这个头文件会分别被DLL和调用DLL的应用程序引入，当被DLL引入时，在DLL中定义_DLL_SAMPLE宏，这样就会在DLL模块中声明函数为导出函数；当被调用DLL的应用程序引入时，就没有定义_DLL_SAMPLE，这样就会声明头文件中的函数为从DLL中的导入函数。&nbsp;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;第二种方法：模块定义文件是一个有着.def文件扩展名的文本文件。它被用于导出一个DLL的函数，和__declspec(dllexport)很相似，但是.def文件并不是Microsoft定义的。一个.def文件中只有两个必需的部分：LIBRARY 和 EXPORTS。
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">LIBRARY&nbsp;DLLSample<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DESCRIPTION&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">my&nbsp;simple&nbsp;DLL</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>EXPORTS<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestDLL&nbsp;@</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;&nbsp;；@1表示这是第一个导出函数<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
&nbsp;&nbsp;&nbsp;第一行，''LIBRARY''是一个必需的部分。它告诉链接器（linker）如何命名你的DLL。下面被标识为''DESCRIPTION''的部分并不是必需的。该语句将字符串写入 .rdata 节，它告诉人们谁可能使用这个DLL，这个DLL做什么或它为了什么（存在）。再下面的部分标识为''EXPORTS''是另一个必需的部分；这个部分使得该函数可以被其它应用程序访问到并且它创建一个导入库。当你生成这个项目时，不仅是一个.dll文件被创建，而且一个文件扩展名为.lib的导出库也被创建了。除了前面的部分以外，这里还有其它四个部分标识为：NAME, STACKSIZE, SECTIONS, 和 VERSION。另外，一个分号(;)开始一个注解，如同''//''在C++中一样。定义了这个文件之后，头文件中的__declspec(dllexport)就不需要声明了。<br><br>&nbsp;&nbsp;&nbsp;三、编写DllMain函数和导出函数<br>&nbsp;&nbsp;&nbsp;DllMain函数是DLL模块的默认入口点。当Windows加载DLL模块时调用这一函数。系统首先调用全局对象的构造函数，然后调用全局函数DLLMain。DLLMain函数不仅在将DLL链接加载到进程时被调用，在DLL模块与进程分离时（以及其它时候）也被调用。
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;_DLL_SAMPLE</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#ifndef&nbsp;_DLL_SAMPLE_H<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLLSample.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">APIENTRY声明DLL函数入口点</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">BOOL&nbsp;APIENTRY&nbsp;DllMain(HANDLE&nbsp;hModule,&nbsp;DWORD&nbsp;ul_reason_for_call,&nbsp;LPVOID&nbsp;lpReserved)<br><img id=Codehighlighter1_218_385_Open_Image onclick="this.style.display='none'; Codehighlighter1_218_385_Open_Text.style.display='none'; Codehighlighter1_218_385_Closed_Image.style.display='inline'; Codehighlighter1_218_385_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_218_385_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_218_385_Closed_Text.style.display='none'; Codehighlighter1_218_385_Open_Image.style.display='inline'; Codehighlighter1_218_385_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_218_385_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_218_385_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">&nbsp;(ul_reason_for_call)<br><img id=Codehighlighter1_250_369_Open_Image onclick="this.style.display='none'; Codehighlighter1_250_369_Open_Text.style.display='none'; Codehighlighter1_250_369_Closed_Image.style.display='inline'; Codehighlighter1_250_369_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_250_369_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_250_369_Closed_Text.style.display='none'; Codehighlighter1_250_369_Open_Image.style.display='inline'; Codehighlighter1_250_369_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>　</span><span id=Codehighlighter1_250_369_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_250_369_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_ATTACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_ATTACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_THREAD_DETACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;DLL_PROCESS_DETACH:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>　}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TestDLL(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;arg)<br><img id=Codehighlighter1_410_451_Open_Image onclick="this.style.display='none'; Codehighlighter1_410_451_Open_Text.style.display='none'; Codehighlighter1_410_451_Closed_Image.style.display='inline'; Codehighlighter1_410_451_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_410_451_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_410_451_Closed_Text.style.display='none'; Codehighlighter1_410_451_Open_Image.style.display='inline'; Codehighlighter1_410_451_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_410_451_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_410_451_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">DLL&nbsp;output&nbsp;arg&nbsp;%d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;arg);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
&nbsp;&nbsp;&nbsp;如果程序员没有为DLL模块编写一个DLLMain</font>函数，系统会从其它运行库中引入一个不做任何操作的缺省DLLMain函数版本。在单个线程启动和终止时，DLLMain函数也被调用。<br>&nbsp;&nbsp;&nbsp;然后，F7编译，就得到一个DLL了。<br>&nbsp;&nbsp;&nbsp; 
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-20 13:49 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/20/90619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Socket编程原理概述</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/19/90516.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Sun, 19 Jul 2009 04:56:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/19/90516.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90516.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/19/90516.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90516.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90516.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1 问题的引入&nbsp; UNIX系统的I/O命令集，是从Maltics和早期系统中的命令演变出来的，其模式为打开一读/写一关闭（open-write-read-close）。在一个用户进程进行I/O操作时，它首先调用&#8220;打开&#8221;获得对指定文件或设备的使用权，并返回称为文件描述符的整型数，以描述用户在打开的文件或设备上进行I/O操作的进程。然后这个用户进程多次调用&#8220...&nbsp;&nbsp;<a href='http://www.cppblog.com/suiaiguo/archive/2009/07/19/90516.html'>阅读全文</a><img src ="http://www.cppblog.com/suiaiguo/aggbug/90516.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-19 12:56 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/19/90516.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows消息机制概述</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Sat, 18 Jul 2009 02:50:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90412.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90412.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90412.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 消息是指什么？&nbsp;&nbsp;&nbsp;&nbsp; 消息系统对于一个win32程序来说十分重要，它是一个程序运行的动力源泉。一个消息，是系统定义的一个32位的值，他唯一的定义了一个事件，向 Windows发出一个通知，告诉应用程序某个事情发生了。例如，单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。&nbsp;&nbsp;&nbsp; 消息本身是作...&nbsp;&nbsp;<a href='http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html'>阅读全文</a><img src ="http://www.cppblog.com/suiaiguo/aggbug/90412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-18 10:50 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COM技术入门基础知识</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/17/90354.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Fri, 17 Jul 2009 08:41:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/17/90354.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90354.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/17/90354.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90354.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90354.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;这几天在学习COM组件技术，网上看了很多教程，发现有一些很基础的东西基本都没有涉及，下面我就结合网上的一些教程加上自己的体会来进行一些总结。<br><br>&nbsp;&nbsp;<strong>&nbsp;(1)COM组件是什么？</strong><br><br>&nbsp;&nbsp;&nbsp;<font color=#000000><span>COM组件由以Win 32动态连接库（DLL）或可执行文件（EXE）形式发布的可执行代码所组成。</span>再向深入了看，以C++为例，COM组件实际上就是一些实现了特定接口的类，而接口都是纯虚类。组件从接口派生而来。我们可以简单的用纯粹的C++的语法形式来描述COM是个什么东西： </font></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;IObject<br><img id=Codehighlighter1_18_105_Open_Image onclick="this.style.display='none'; Codehighlighter1_18_105_Open_Text.style.display='none'; Codehighlighter1_18_105_Closed_Image.style.display='inline'; Codehighlighter1_18_105_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_18_105_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_18_105_Closed_Text.style.display='none'; Codehighlighter1_18_105_Open_Image.style.display='inline'; Codehighlighter1_18_105_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>　　</span><span id=Codehighlighter1_18_105_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_18_105_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Function1(<img src="http://www.cppblog.com/Images/dot.gif">)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Function2(<img src="http://www.cppblog.com/Images/dot.gif">)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif">.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>　　}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyObject&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;IObject<br><img id=Codehighlighter1_144_227_Open_Image onclick="this.style.display='none'; Codehighlighter1_144_227_Open_Text.style.display='none'; Codehighlighter1_144_227_Closed_Image.style.display='inline'; Codehighlighter1_144_227_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_144_227_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_144_227_Closed_Text.style.display='none'; Codehighlighter1_144_227_Open_Image.style.display='inline'; Codehighlighter1_144_227_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>　　</span><span id=Codehighlighter1_144_227_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_144_227_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_182_186_Open_Image onclick="this.style.display='none'; Codehighlighter1_182_186_Open_Text.style.display='none'; Codehighlighter1_182_186_Closed_Image.style.display='inline'; Codehighlighter1_182_186_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_182_186_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_182_186_Closed_Text.style.display='none'; Codehighlighter1_182_186_Open_Image.style.display='inline'; Codehighlighter1_182_186_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>　　　　</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Function1(<img src="http://www.cppblog.com/Images/dot.gif">)</span><span id=Codehighlighter1_182_186_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_182_186_Open_Text><span style="COLOR: #000000">{<img src="http://www.cppblog.com/Images/dot.gif">}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_214_218_Open_Image onclick="this.style.display='none'; Codehighlighter1_214_218_Open_Text.style.display='none'; Codehighlighter1_214_218_Closed_Image.style.display='inline'; Codehighlighter1_214_218_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_214_218_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_214_218_Closed_Text.style.display='none'; Codehighlighter1_214_218_Open_Image.style.display='inline'; Codehighlighter1_214_218_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>　　　　</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Function2(<img src="http://www.cppblog.com/Images/dot.gif">)</span><span id=Codehighlighter1_214_218_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_214_218_Open_Text><span style="COLOR: #000000">{<img src="http://www.cppblog.com/Images/dot.gif">}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><img src="http://www.cppblog.com/Images/dot.gif">.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>　　}</span></span><span style="COLOR: #000000">;&nbsp;</span></div>
<p>&nbsp;<br>　　看清楚了吗？IObject就是我们常说的接口，MyObject就是所谓的COM组件。切记切记接口都是纯虚类，它所包含的函数都是纯虚函数，而且它没有成员变量。而COM组件就是从这些纯虚类继承下来的派生类，它实现了这些虚函数，仅此而已。从上面也可以看出，COM组件是以 C++为基础的，特别重要的是虚函数和多态性的概念，COM中所有函数都是虚函数，都必须通过虚函数表VTable来调用，这一点是无比重要的，必需时刻牢记在心。<br><br>&nbsp;&nbsp;&nbsp;<strong>(2) COM组件有三个最基本的接口类，分别是IUnknown、IClassFactory、IDispatch。</strong> </p>
<p>　　COM规范规定任何组件、任何接口都必须从IUnknown继承，IUnknown包含三个函数，分别是 QueryInterface、AddRef、Release。这三个函数是无比重要的，而且它们的排列顺序也是不可改变的。QueryInterface用于查询组件实现的其它接口，说白了也就是看看这个组件的父类中还有哪些接口类，AddRef用于增加引用计数，Release用于减少引用计数。引用计数也是COM中的一个非常重要的概念。大体上简单的说来可以这么理解，COM组件是个DLL，当客户程序要用它时就要把它装到内存里。另一方面，一个组件也不是只给你一个人用的，可能会有很多个程序同时都要用到它。但实际上DLL只装载了一次，即内存中只有一个COM组件，那COM组件由谁来释放？由客户程序吗？不可能，因为如果你释放了组件，那别人怎么用，所以只能由COM组件自己来负责。所以出现了引用计数的概念，COM维持一个计数，记录当前有多少人在用它，每多一次调用计数就加一，少一个客户用它就减一，当最后一个客户释放它的时侯，COM知道已经没有人用它了，它的使用已经结束了，那它就把它自己给释放了。引用计数是COM编程里非常容易出错的一个地方，但所幸VC的各种各样的类库里已经基本上把AddRef的调用给隐含了，在我的印象里，我编程的时侯还从来没有调用过AddRef，我们只需在适当的时侯调用Release。至少有两个时侯要记住调用Release，第一个是调用了 QueryInterface以后，第二个是调用了任何得到一个接口的指针的函数以后，记住多查MSDN 以确定某个函数内部是否调用了AddRef，如果是的话那调用Release的责任就要归你了。 IUnknown的这三个函数的实现非常规范但也非常烦琐，容易出错，所幸的事我们可能永远也不需要自己来实现它们。 </p>
<p>　　IClassFactory的作用是创建COM组件。我们已经知道COM组件实际上就是一个类，那我们平常是怎么实例化一个类对象的？是用&#8216;new&#8217;命令!很简单吧，COM组件也一样如此。但是谁来new它呢？不可能是客户程序，因为客户程序不可能知道组件的类名字，如果客户知道组件的类名字那组件的可重用性就要打个大大的折扣了，事实上客户程序只不过知道一个代表着组件的128位的数字串而已，这个等会再介绍。所以客户无法自己创建组件，而且考虑一下，如果组件是在远程的机器上，你还能new出一个对象吗？所以创建组件的责任交给了一个单独的对象，这个对象就是类厂。每个组件都必须有一个与之相关的类厂，这个类厂知道怎么样创建组件，当客户请求一个组件对象的实例时，实际上这个请求交给了类厂，由类厂创建组件实例，然后把实例指针交给客户程序。这个过程在跨进程及远程创建组件时特别有用，因为这时就不是一个简单的new操作就可以的了，它必须要经过调度，而这些复杂的操作都交给类厂对象去做了。IClassFactory最重要的一个函数就是CreateInstance，顾名思议就是创建组件实例，一般情况下我们不会直接调用它，API函数都为我们封装好它了，只有某些特殊情况下才会由我们自己来调用它，这也是VC编写COM组件的好处，使我们有了更多的控制机会，而VB给我们这样的机会则是太少太少了。 </p>
<p>　　IDispatch叫做调度接口。它的作用何在呢？这个世上除了C++还有很多别的语言，比如VB、 VJ、VBScript、JavaScript等等。可以这么说，如果这世上没有这么多乱七八糟的语言，那就不会有IDispatch。:-) 我们知道COM组件是C++类，是靠虚函数表来调用函数的，对于VC来说毫无问题，这本来就是针对C++而设计的，以前VB不行，现在VB也可以用指针了，也可以通过VTable来调用函数了，VJ也可以，但还是有些语言不行，那就是脚本语言，典型的如 VBScript、JavaScript。不行的原因在于它们并不支持指针，连指针都不能用还怎么用多态性啊，还怎么调这些虚函数啊。唉，没办法，也不能置这些脚本语言于不顾吧，现在网页上用的都是这些脚本语言，而分布式应用也是COM组件的一个主要市场，它不得不被这些脚本语言所调用，既然虚函数表的方式行不通，我们只能另寻他法了。时势造英雄，IDispatch应运而生。:-) 调度接口把每一个函数每一个属性都编上号，客户程序要调用这些函数属性的时侯就把这些编号传给IDispatch接口就行了，IDispatch再根据这些编号调用相应的函数，仅此而已。当然实际的过程远比这复杂，仅给一个编号就能让别人知道怎么调用一个函数那不是天方夜潭吗，你总得让别人知道你要调用的函数要带什么参数，参数类型什么以及返回什么东西吧，而要以一种统一的方式来处理这些问题是件很头疼的事。IDispatch接口的主要函数是Invoke，客户程序都调用它，然后Invoke再调用相应的函数，如果看一看MS的类库里实现 Invoke的代码就会惊叹它实现的复杂了，因为你必须考虑各种参数类型的情况，所幸我们不需要自己来做这件事，而且可能永远也没这样的机会。:-) </p>
<p>&nbsp;&nbsp;<strong>&nbsp;(3) dispinterface接口、Dual接口以及Custom接口</strong> </p>
<p>　　这一小节放在这里似乎不太合适，因为这是在ATL编程时用到的术语。我在这里主要是想谈一下自动化接口的好处及缺点，用这三个术语来解释可能会更好一些，而且以后迟早会遇上它们，我将以一种通俗的方式来解释它们，可能并非那么精确，就好象用伪代码来描述算法一样。-:) </p>
<p>　　所谓的自动化接口就是用IDispatch实现的接口。我们已经讲解过IDispatch的作用了，它的好处就是脚本语言象VBScript、 JavaScript也能用COM组件了，从而基本上做到了与语言无关它的缺点主要有两个，第一个就是速度慢效率低。这是显而易见的，通过虚函数表一下子就可以调用函数了，而通过Invoke则等于中间转了道手续，尤其是需要把函数参数转换成一种规范的格式才去调用函数，耽误了很多时间。所以一般若非是迫不得已我们都想用VTable的方式调用函数以获得高效率。第二个缺点就是只能使用规定好的所谓的自动化数据类型。如果不用IDispatch我们可以想用什么数据类型就用什么类型，VC会自动给我们生成相应的调度代码。而用自动化接口就不行了，因为Invoke的实现代码是VC事先写好的，而它不能事先预料到我们要用到的所有类型，它只能根据一些常用的数据类型来写它的处理代码，而且它也要考虑不同语言之间的数据类型转换问题。所以VC自动化接口生成的调度代码只适用于它所规定好的那些数据类型，当然这些数据类型已经足够丰富了，但不能满足自定义数据结构的要求。你也可以自己写调度代码来处理你的自定义数据结构，但这并不是一件容易的事。考虑到IDispatch的种种缺点(它还有一个缺点，就是使用麻烦，:-) )现在一般都推荐写双接口组件，称为dual接口，实际上就是从IDispatch继承的接口。我们知道任何接口都必须从 IUnknown继承，IDispatch接口也不例外。那从IDispatch继承的接口实际上就等于有两个基类，一个是IUnknown，一个是IDispatch，所以它可以以两种方式来调用组件，可以通过 IUnknown用虚函数表的方式调用接口方法，也可以通过IDispatch::Invoke自动化调度来调用。这就有了很大的灵活性，这个组件既可以用于C++的环境也可以用于脚本语言中，同时满足了各方面的需要。 </p>
<p>　　相对比的，dispinterface是一种纯粹的自动化接口，可以简单的就把它看作是IDispatch接口 (虽然它实际上不是的)，这种接口就只能通过自动化的方式来调用，COM组件的事件一般都用的是这种形式的接口。 </p>
<p>　　Custom接口就是从IUnknown接口派生的类，显然它就只能用虚函数表的方式来调用接口了 </p>
<p>&nbsp;&nbsp;<strong>&nbsp;(4) COM组件有三种，进程内、本地、远程。对于后两者情况必须调度接口指针及函数参数。</strong> </p>
<p>　　COM是一个DLL，它有三种运行模式。它可以是进程内的，即和调用者在同一个进程内，也可以和调用者在同一个机器上但在不同的进程内，还可以根本就和调用者在两台机器上。这里有一个根本点需要牢记，就是COM组件它只是一个DLL，它自己是运行不起来的，必须有一个进程象父亲般照顾它才行，即COM组件必须在一个进程内.那谁充当看护人的责任呢？先说说调度的问题。调度是个复杂的问题，以我的知识还讲不清楚这个问题，我只是一般性的谈谈几个最基本的概念。我们知道对于WIN32程序，每个进程都拥有4GB的虚拟地址空间，每个进程都有其各自的编址，同一个数据块在不同的进程里的编址很可能就是不一样的，所以存在着进程间的地址转换问题。这就是调度问题。对于本地和远程进程来说，DLL 和客户程序在不同的编址空间，所以要传递接口指针到客户程序必须要经过调度。Windows 已经提供了现成的调度函数，就不需要我们自己来做这个复杂的事情了。对远程组件来说函数的参数传递是另外一种调度。DCOM是以RPC为基础的，要在网络间传递数据必须遵守标准的网上数据传输协议，数据传递前要先打包，传递到目的地后要解包，这个过程就是调度，这个过程很复杂，不过Windows已经把一切都给我们做好了，一般情况下我们不需要自己来编写调度DLL。 </p>
<p>　　我们刚说过一个COM组件必须在一个进程内。对于本地模式的组件一般是以EXE的形式出现，所以它本身就已经是一个进程。对于远程DLL，我们必须找一个进程，这个进程必须包含了调度代码以实现基本的调度。这个进程就是dllhost.exe。这是COM默认的DLL代理。实际上在分布式应用中，我们应该用MTS来作为DLL代理，因为MTS有着很强大的功能，是专门的用于管理分布式DLL组件的工具。 </p>
<p>　　调度离我们很近又似乎很远，我们编程时很少关注到它，这也是COM的一个优点之一，既平台无关性，无论你是远程的、本地的还是进程内的，编程是一样的，一切细节都由COM自己处理好了，所以我们也不用深究这个问题，只要有个概念就可以了，当然如果你对调度有自己特殊的要求就需要深入了解调度的整个过程了，这里推荐一本《COM+技术内幕》，这绝对是一本讲调度的好书。 </p>
<p>&nbsp;&nbsp;&nbsp;<strong>(5) COM组件的核心是IDL。</strong> </p>
<p>　　我们希望软件是一块块拼装出来的，但不可能是没有规定的胡乱拼接，总是要遵守一定的标准，各个模块之间如何才能亲密无间的合作，必须要事先共同制订好它们之间交互的规范，这个规范就是接口。我们知道接口实际上都是纯虚类，它里面定义好了很多的纯虚函数，等着某个组件去实现它，这个接口就是两个完全不相关的模块能够组合在一起的关键试想一下如果我们是一个应用软件厂商，我们的软件中需要用到某个模块，我们没有时间自己开发，所以我们想到市场上找一找看有没有这样的模块，我们怎么去找呢？也许我们需要的这个模块在业界已经有了标准，已经有人制订好了标准的接口，有很多组件工具厂商已经在自己的组件中实现了这个接口，那我们寻找的目标就是这些已经实现了接口的组件，我们不关心组件从哪来，它有什么其它的功能，我们只关心它是否很好的实现了我们制订好的接口。这种接口可能是业界的标准，也可能只是你和几个厂商之间内部制订的协议，但总之它是一个标准，是你的软件和别人的模块能够组合在一起的基础，是COM组件通信的标准。 </p>
<p>　　COM具有语言无关性，它可以用任何语言编写，也可以在任何语言平台上被调用。但至今为止我们一直是以C++的环境中谈COM，那它的语言无关性是怎么体现出来的呢？或者换句话说，我们怎样才能以语言无关的方式来定义接口呢？前面我们是直接用纯虚类的方式定义的，但显然是不行的，除了C++谁还认它呢？正是出于这种考虑，微软决定采用IDL来定义接口。说白了，IDL实际上就是一种大家都认识的语言，用它来定义接口，不论放到哪个语言平台上都认识它。我们可以想象一下理想的标准的组件模式，我们总是从IDL开始，先用IDL制订好各个接口，然后把实现接口的任务分配不同的人，有的人可能善长用VC，有的人可能善长用VB，这没关系，作为项目负责人我不关心这些，我只关心你把最终的DLL 拿给我。这是一种多么好的开发模式，可以用任何语言来开发，也可以用任何语言来欣赏你的开发成果。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;让我们看IUnknow接口的定义文件是怎样的。<br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">[<br>&nbsp;&nbsp;local,<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;uuid(</span><span style="COLOR: #000000">00000000</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">0000</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">0000</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">C000</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">000000000046</span><span style="COLOR: #000000">),<br>&nbsp;&nbsp;pointer_default(unique)<br>]<br><br></span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;IUnknown<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;[unique]&nbsp;IUnknown&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">LPUNKNOWN;<br><br>cpp_quote(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">//////////////////////////////////////////////////////////////////</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br>cpp_quote(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">//&nbsp;IID_IUnknown&nbsp;and&nbsp;all&nbsp;other&nbsp;system&nbsp;IIDs&nbsp;are&nbsp;provided&nbsp;in&nbsp;UUID.LIB</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br>cpp_quote(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">//&nbsp;Link&nbsp;that&nbsp;library&nbsp;in&nbsp;with&nbsp;your&nbsp;proxies,&nbsp;clients&nbsp;and&nbsp;servers</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br>cpp_quote(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">//////////////////////////////////////////////////////////////////</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;HRESULT&nbsp;QueryInterface(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">]&nbsp;REFIID&nbsp;riid,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">,&nbsp;iid_is(riid)]&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">ppvObject);<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;AddRef();<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;Release();<br>}<br><br>[local]属性禁止产生网络代码。<br>[</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">]属性是表明定义的是一个COM接口，而不是DEC风格的接口。<br>[uuid]属性给接口一个GUID。<br>[unique]属性表明null(空)指针为一个合法的参数值。<br>[pointer_defaul]属性所有的内嵌指针指定一个默认指针属性<br>typedef&nbsp;[unique]&nbsp;IUnknown&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">LPUNKNOWN;这是一个类型定义<br>cpp_quote这个比较有趣，这是一个在idl文件写注解的方法。这些注解将保存到</span><span style="COLOR: #000000">***</span><span style="COLOR: #000000">.h和</span><span style="COLOR: #000000">***</span><span style="COLOR: #000000">_i.c文件中<br>[</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">]表示这个参数是入参<br>[</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">]表示这个参数是出参<br>[iid_is(riid)]表示这个参数需要前一个的riid&nbsp;参数。</span></div>
<p>&nbsp;<br></p>
<p>&nbsp;&nbsp;&nbsp;<strong>(6) COM组件的运行机制，即COM是怎么跑起来的。</strong> </p>
<p>　　这部分我们将构造一个创建COM组件的最小框架结构，然后看一看其内部处理流程是怎样的 </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　IUnknown&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pUnk</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　IObject&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pObject</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　CoInitialize(NULL);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　CoCreateInstance(CLSID_Object,&nbsp;CLSCTX_INPROC_SERVER,&nbsp;NULL,&nbsp;IID_IUnknown,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pUnk);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　pUnk</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryInterface(IID_IOjbect,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pObject);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　pUnk</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　pObject</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Func();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　pObject</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　CoUninitialize();&nbsp;</span></div>
<p><br>　　这就是一个典型的创建COM组件的框架，不过我的兴趣在CoCreateInstance身上，让我们来看看它内部做了一些什么事情。以下是它内部实现的一个伪代码: </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　　CoCreateInstance(<img src="http://www.cppblog.com/Images/dot.gif">.)<br><img id=Codehighlighter1_31_308_Open_Image onclick="this.style.display='none'; Codehighlighter1_31_308_Open_Text.style.display='none'; Codehighlighter1_31_308_Closed_Image.style.display='inline'; Codehighlighter1_31_308_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_31_308_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_31_308_Closed_Text.style.display='none'; Codehighlighter1_31_308_Open_Image.style.display='inline'; Codehighlighter1_31_308_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>　　　　</span><span id=Codehighlighter1_31_308_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_31_308_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif">.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　IClassFactory&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pClassFactory</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　CoGetClassObject(CLSID_Object,&nbsp;CLSCTX_INPROC_SERVER,&nbsp;NULL,&nbsp;IID_IClassFactory,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pClassFactory);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　pClassFactory</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">CreateInstance(NULL,&nbsp;IID_IUnknown,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pUnk);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　pClassFactory</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif">..<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>　　　}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>　　这段话的意思就是先得到类厂对象，再通过类厂创建组件从而得到IUnknown指针。继续深入一步，看看CoGetClassObject的内部伪码： </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">　　　CoGetClassObject(<img src="http://www.cppblog.com/Images/dot.gif">..)<br><img id=Codehighlighter1_30_177_Open_Image onclick="this.style.display='none'; Codehighlighter1_30_177_Open_Text.style.display='none'; Codehighlighter1_30_177_Closed_Image.style.display='inline'; Codehighlighter1_30_177_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_30_177_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_30_177_Closed_Text.style.display='none'; Codehighlighter1_30_177_Open_Image.style.display='inline'; Codehighlighter1_30_177_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>　　　</span><span id=Codehighlighter1_30_177_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_30_177_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">通过查注册表CLSID_Object，得知组件DLL的位置、文件名<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">装入DLL库<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">使用函数GetProcAddress(<img src="http://www.cppblog.com/Images/dot.gif">)得到DLL库中函数DllGetClassObject的函数指针。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">调用DllGetClassObject&nbsp;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">　　　}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　DllGetClassObject是干什么的，它是用来获得类厂对象的。只有先得到类厂才能去创建组件.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　下面是DllGetClassObject的伪码：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　DllGetClassObject(<img src="http://www.cppblog.com/Images/dot.gif">)<br><img id=Codehighlighter1_294_489_Open_Image onclick="this.style.display='none'; Codehighlighter1_294_489_Open_Text.style.display='none'; Codehighlighter1_294_489_Closed_Image.style.display='inline'; Codehighlighter1_294_489_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_294_489_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_294_489_Closed_Text.style.display='none'; Codehighlighter1_294_489_Open_Image.style.display='inline'; Codehighlighter1_294_489_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>　　　　</span><span id=Codehighlighter1_294_489_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_294_489_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　CFactory</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pFactory</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CFactory;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">类厂对象</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">　　　　pFactory</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryInterface(IID_IClassFactory,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pClassFactory);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">查询IClassFactory指针</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">　　　　pFactory</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>　　　　}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　CoGetClassObject的流程已经到此为止，现在返回CoCreateInstance，看看CreateInstance的伪码：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　　　　CFactory::CreateInstance(<img src="http://www.cppblog.com/Images/dot.gif">..)<br><img id=Codehighlighter1_603_766_Open_Image onclick="this.style.display='none'; Codehighlighter1_603_766_Open_Text.style.display='none'; Codehighlighter1_603_766_Closed_Image.style.display='inline'; Codehighlighter1_603_766_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_603_766_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_603_766_Closed_Text.style.display='none'; Codehighlighter1_603_766_Open_Image.style.display='inline'; Codehighlighter1_603_766_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>　　　　</span><span id=Codehighlighter1_603_766_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_603_766_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif">..<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　CObject&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pObject&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CObject;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">组件对象</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">　　　　pObject</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryInterface(IID_IUnknown,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pUnk);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　pObject</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　　　　<img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif"><img src="http://www.cppblog.com/Images/dot.gif">..<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>　　　　}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>　　下图是从VCKBASE中COPY来的一个例程图，从图中可以清楚的看到COM的整个流程。 </p>
<p>&nbsp;<img height=668 alt="" src="http://www.cppblog.com/images/cppblog_com/suiaiguo/COM.gif" width=665 border=0></p>
<p>&nbsp;<strong>&nbsp;&nbsp;(7) 一个典型的自注册的COM DLL所必有的四个函数 </strong></p>
<p>　　DllGetClassObject:用于获得类厂指针 </p>
<p>　　DllRegisterServer:注册一些必要的信息到注册表中 </p>
<p>　　DllUnregisterServer:卸载注册信息 </p>
<p>　　DllCanUnloadNow:系统空闲时会调用这个函数，以确定是否可以卸载DLL </p>
<p>　　DLL还有一个函数是DllMain,这个函数在COM中并不要求一定要实现它，但是在VC生成的组件中自动都包含了它，它的作用主要是得到一个全局的实例对象。 </p>
<p>&nbsp;&nbsp;&nbsp;<strong>(8) 注册表在COM中的重要作用</strong> </p>
<p>　　首先要知道GUID的概念，COM中所有的类、接口、类型库都用GUID来唯一标识，GUID是一个128位的字串，根据特制算法生成的GUID可以保证是全世界唯一的。 COM组件的创建，查询接口都是通过注册表进行的。有了注册表，应用程序就不需要知道组件的DLL文件名、位置，只需要根据CLSID查就可以了。当版本升级的时侯，只要改一下注册表信息就可以神不知鬼不觉的转到新版本的DLL。 </p>
<p>&nbsp;&nbsp;<strong>&nbsp;(9) 如何注册和卸载COM组件</strong><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可能大家也发现了，在调用整个COM组件的过程中，并没有代码来明确的执行加载DLL的操作，那么到底COM是怎样被调用到得呢？实际上，在COM组件使用前，我们必须要先把它进行注册。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;打开命令行窗口，到DLL的目录下，运行regsvr32 xxx.dll（xxx.dll就是你的包含COM组件的DLL文件），运行这个命令时，DLL文件中的DllRegisterServer就会被系统调用，这个COM组件的信息就注入到注册表中去了，这时程序就可以通过GUID从注册表中找到你的COM组件了。相反，如果你想卸载你的COM组件，只需要运行regsvr32 /u xxx.dll（多了个/u），DLL文件中的DllUnregisterServer就是被系统调用，这个COM组件的信息就被从注册表中去除了，也就完成了卸载。<br><br>&nbsp;&nbsp;&nbsp;<strong>(10)为什么要用COM</strong> </p>
<p>　　软件工程发展到今天，从一开始的结构化编程，到面向对象编程，再到现在的COM编程，目标只有一个，就是希望软件能象积方块一样是累起来的，是组装起来的，而不是一点点编出来的。结构化编程是函数块的形式，通过把一个软件划分成许多模块，每个模块完成各自不同的功能，尽量做到高内聚低藕合，这已经是一个很好的开始，我们可以把不同的模块分给不同的人去做，然后合到一块，这已经有了组装的概念了。软件工程的核心就是要模块化，最理想的情况就是100%内聚0%藕合。整个软件的发展也都是朝着这个方向走的。结构化编程方式只是一个开始。下一步就出现了面向对象编程，它相对于面向功能的结构化方式是一个巨大的进步。我们知道整个自然界都是由各种各样不同的事物组成的，事物之间存在着复杂的千丝万缕的关系，而正是靠着事物之间的联系、交互作用，我们的世界才是有生命力的才是活动的。我们可以认为在自然界中事物做为一个概念，它是稳定的不变的，而事物之间的联系是多变的、运动的。事物应该是这个世界的本质所在。面向对象的着眼点就是事物，就是这种稳定的概念。每个事物都有其固有的属性，都有其固有的行为，这些都是事物本身所固有的东西，而面向对象的方法就是描述出这种稳定的东西。而面向功能的模块化方法它的着眼点是事物之间的联系，它眼中看不到事物的概念它只注重功能，我们平常在划分模块的时侯有没有想过这个函数与哪些对象有关呢？很少有人这么想，一个函数它实现一种功能，这个功能必定与某些事物想联系，我们没有去掌握事物本身而只考虑事物之间是怎么相互作用而完成一个功能的。说白了，这叫本末倒置，也叫急功近利，因为不是我们智慧不够，只是因为我们没有多想一步。面向功能的结构化方法因为它注意的只是事物之间的联系，而联系是多变的，事物本身可能不会发生大的变化，而联系则是很有可能发生改变的，联系一变，那就是另一个世界了，那就是另一种功能了。如果我们用面向对象的方法，我们就可以以不变应万变，只要事先把事物用类描述好，我们要改变的只是把这些类联系起来的方法，只是重新使用我们的类库，而面向过程的方法因为它构造的是一个不稳定的世界，所以一点小小的变化也可能导致整个系统都要改变。然而面向对象方法仍然有问题，问题在于重用的方法。搭积木式的软件构造方法的基础是有许许多多各种各样的可重用的部件、模块。我们首先想到的是类库，因为我们用面向对象的方法产生的直接结果就是许多的类。但类库的重用是基于源码的方式，这是它的重大缺陷。首先它限制了编程语言，你的类库总是用一种语言写的吧，那你就不能拿到别的语言里用了。其次你每次都必须重新编译，只有编译了才能与你自己的代码结合在一起生成可执行文件。在开发时这倒没什么，关键在于开发完成后，你的EXE都已经生成好了，如果这时侯你的类库提供厂商告诉你他们又做好了一个新的类库，功能更强大速度更快，而你为之心动又想把这新版的类库用到你自己的程序中，那你就必须重新编译、重新调试！这离我们理想的积木式软件构造方法还有一定差距，在我们的设想里希望把一个模块拿出来再换一个新的模块是非常方便的事，可是现在不但要重新编译，还要冒着很大的风险，因为你可能要重新改变你自己的代码。另一种重用方式很自然地就想到了是DLL的方式。Windows里到处是DLL，它是Windows 的基础，但DLL也有它自己的缺点。总结一下它至少有四点不足。(1)函数重名问题。DLL里是一个一个的函数，我们通过函数名来调用函数，那如果两个DLL里有重名的函数怎么办？(2)各编译器对C＋＋函数的名称修饰不兼容问题。对于C＋＋函数，编译器要根据函数的参数信息为它生成修饰名，DLL库里存的就是这个修饰名，但是不同的编译器产生修饰的方法不一样，所以你在VC 里编写的DLL在BC里就可以用不了。不过也可以用extern "C";来强调使用标准的C函数特性，关闭修饰功能，但这样也丧失了C＋＋的重载多态性功能。(3)路径问题。放在自己的目录下面，别人的程序就找不到，放在系统目录下，就可能有重名的问题。而真正的组件应该可以放在任何地方甚至可以不在本机，用户根本不需考虑这个问题。(4)DLL与EXE的依赖问题。我们一般都是用隐式连接的方式，就是编程的时侯指明用什么DLL，这种方式很简单，它在编译时就把EXE与DLL绑在一起了。如果DLL发行了一个新版本，我们很有必要重新链接一次，因为DLL里面函数的地址可能已经发生了改变。DLL的缺点就是COM的优点。首先我们要先把握住一点，COM和DLL一样都是基于二进制的代码重用，所以它不存在类库重用时的问题。另一个关键点是，COM本身也是DLL，既使是ActiveX控件.ocx它实际上也是DLL，所以说DLL在还是有重用上有很大的优势，只不过我们通过制订复杂的COM协议，通COM本身的机制改变了重用的方法，以一种新的方法来利用DLL，来克服DLL本身所固有的缺陷，从而实现更高一级的重用方法。COM没有重名问题，因为根本不是通过函数名来调用函数，而是通过虚函数表，自然也不会有函数名修饰的问题。路径问题也不复存在，因为是通过查注册表来找组件的，放在什么地方都可以，即使在别的机器上也可以。也不用考虑和EXE的依赖关系了，它们二者之间是松散的结合在一起，可以轻松的换上组件的一个新版本，而应用程序混然不觉。<br></p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-17 16:41 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/17/90354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>各种符号的英文表达</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90260.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Thu, 16 Jul 2009 10:11:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90260.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90260.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90260.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90260.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90260.html</trackback:ping><description><![CDATA[．period 句号 <br>，comma 逗号 <br>：colon 冒号 <br>；semicolon 分号 <br>！exclamation 惊叹号 <br>？question mark 问号 <br>￣hyphen 连字符 <br>'apostrophe 省略号；所有格符号 <br>—dash 破折号 <br>&#8216; &#8217;single quotation marks 单引号 <br>&#8220; &#8221;double quotation marks 双引号 <br>( )parentheses 圆括号 <br>[ ]square brackets 方括号 <br>《 》French quotes 法文引号；书名号 <br>...ellipsis 省略号 <br>&#168;tandem colon 双点号 <br>"ditto 同上 <br>‖parallel 双线号 <br>／virgule 斜线号 <br>＆ampersand = and <br>～swung dash 代字号 <br>&#167;section; division 分节号 <br>&#8594;arrow 箭号；参见号 <br>＋plus 加号；正号 <br>－minus 减号；负号 <br>&#177;plus or minus 正负号 <br>&#215;is multiplied by 乘号 <br>&#247;is divided by 除号 <br>＝is equal to 等于号 <br>&#8800;is not equal to 不等于号 <br>&#8801;is equivalent to 全等于号 <br>≌is equal to or approximately equal to 等于或约等于号 <br>≈is approximately equal to 约等于号 <br>＜is less than 小于号 <br>＞is more than 大于号 <br>≮is not less than 不小于号 <br>≯is not more than 不大于号 <br>&#8804;is less than or equal to 小于或等于号 <br>&#8805;is more than or equal to 大于或等于号 <br>％per cent 百分之&#8230; <br>&#8240;per mill 千分之&#8230; <br>&#8734;infinity 无限大号 <br>&#8733;varies as 与&#8230;成比例 <br>&#8730;(square) root 平方根 <br>∵since; because 因为 <br>&#8756;hence 所以 <br>∷equals, as (proportion) 等于，成比例 <br>&#8736;angle 角 <br>⌒semicircle 半圆 <br>⊙circle 圆 <br>○circumference 圆周 <br>&#960;pi 圆周率 <br>△triangle 三角形 <br>&#8869;perpendicular to 垂直于 <br>&#8746;union of 并，合集 <br>&#8745;intersection of 交，通集 <br>&#8747;the integral of &#8230;的积分 <br>∑(sigma) summation of 总和 <br>&#176;degree 度 <br>&#8242;minute 分 <br>&#8243;second 秒 <br>＃number &#8230;号 <br>℃Celsius system 摄氏度 <br>＠at 单价<br>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-16 18:11 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/16/90260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>KMP算法</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90237.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Thu, 16 Jul 2009 07:47:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90237.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90237.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90237.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90237.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90237.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;KMP 匹配算法是由 "Knuth&nbsp; Morris&nbsp; Pratt"&nbsp; 提出的一种快速的模式匹配算法。&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;hint：不为自身的最大首尾重复子串长度</p>
<p>&nbsp;&nbsp;&nbsp;1.待解决的问题：假设P为给定的子串，T是待查找的字符串，要求从T中找出与P相同的所有子串，这称为模式匹配问题。 (可以给出子串在T中的位置) (下文中提到的P和T分别为子串和目标串)</p>
<p>&nbsp;&nbsp;&nbsp;让我们先来看个例题：</p>
<p>&nbsp;&nbsp;&nbsp;T:&nbsp;&nbsp; t0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t1&nbsp;&nbsp;&nbsp;&nbsp; t2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t3 .... tm-1 ... tn-1</p>
<p>&nbsp;&nbsp;&nbsp;P:&nbsp;&nbsp; p0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p1&nbsp;&nbsp;&nbsp;&nbsp; p2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p3 .....pm-1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;从T的最左边开始比较，使得 TK = PK，则匹配成功。 </p>
<p>&nbsp;&nbsp;&nbsp;2.解决模式匹配问题的方案：</p>
<p>&nbsp;&nbsp;&nbsp;A：朴素的模式匹配算法(思路简单,但不够简便，时间长，有回溯)：最简单和最直接的做法，用P中的字符依次与T中的字符进行比较，遇到不相等的字符，则可将P右移一个字符，重新进行比较，直到某次匹配成功或者到达P的最右字符移出T为止。</p>
<p>&nbsp;&nbsp;&nbsp;如：若P="aaaba", T="aaabbaaaba", 则匹配过程如下图</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;T:&nbsp;&nbsp;&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; b&nbsp;&nbsp; b&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; b&nbsp; a</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;P:&nbsp;&nbsp;&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; b&nbsp;&nbsp; a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; b&nbsp;&nbsp; a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .....</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; a&nbsp;&nbsp; b&nbsp; a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;从上不难分析，最坏的情况是&#8220;每次比较都在最后一个字符出现不等，每趟最多比较M次，最多比较N-M+1趟，总的比较次数最多为M*(N-M+1)&#8221; ，时间复杂性为0(M*N)。 在P右移一位时，不管上一趟比较的中间结果是什么，因此回溯是不可避免的(如：前3个aaa 不需要一位一位的移 ) 。下面我来介绍无回溯的KMP算法。</p>
<p>&nbsp;&nbsp;&nbsp;3.KMP算法解决匹配中哪些主要问题：</p>
<p>&nbsp;&nbsp;&nbsp;A.当字符串比较出现不等时，确定下一趟比较前，应该将P右移多少个字符；&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;B. P右移后，应该从哪个字符开始和T中刚才比较时不等的那个字符继续开始比较。</p>
<p>&nbsp;&nbsp;&nbsp; 我们通过朴素模式匹配的例子来引出问题。在第一次比较过程中失败的是P的第4个字符b，这表明P的前4个字符是成功的。模式P的第3个字符b在它的前3个字符(aaa)中并未出现。因此，在下一次比较时候，至少要将P向后移4个字符；再看P的第一个字符与最后一个字符是相同的，因此将P右移4个字符后，再从第一个字符比较，肯定也是不等的。综上所诉：应该将P右移5个字符，再从P的第0个字符和T的第5个字符开始比较！</p>
<p>&nbsp;&nbsp;&nbsp;KMP算法核心：KMP算法借助于一个辅助数组next来确定当匹配过程中出现不等时，模式P右移的位置和开始比较的位置。next[i]的取值只与模式P本身的前i+1项有关，而与目标T无关。匹配过程中遇到Pi不等于Tj时，若next[i]&gt;=0，则应将P右移i-next[i]位个字符，用P中的第next[i]个字符与Tj 进行比较；若：next[i]= -1，P中的任何字符都不必再与Tj比较，而应将P右移i+1个字符，从P0和Tj+1从新开始下一轮比较(可能不太好理解，自己找个例子，对着话一句一句试试看)</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;因此只要计算出与模式P相关的next数组，按上面的含义，就可以很容易地给出串的匹配算法。(问题就这样转化了)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;C.next的计算：以P = " 01001010100001"为例。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; i&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 2&nbsp;&nbsp; 3&nbsp;&nbsp; 4&nbsp;&nbsp; 5&nbsp;&nbsp; 6&nbsp;&nbsp;&nbsp; .....&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp; .....</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;j(next[i]) :&nbsp;&nbsp;&nbsp;&nbsp; -1&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 2&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp; .....</p>
<p>&nbsp;&nbsp;&nbsp;如1：我们要算next[2]的值,有关的为P本身的前2个字符0,1。在字符串01中，寻找出&#8220;左右相同的最大字符串，此字符串所含字符的个数就为next[i]的值&#8221;而0不等于1，相同字符串不存在，所以next[i] = 0；</p>
<p>&nbsp;&nbsp;&nbsp;如2：我们要算next[6]的值，有关的为P本身前6个字符010010&nbsp;。此字符串中010 = 010左右相同的最大字符串为010，个数为3。所以next[i]=3；</p>
<p>&nbsp;&nbsp;&nbsp;如3：我们要算next[5]的值，有关的为P本身前5个字符01001。此字符串中 01=01 左右相同的最大字符串为01，个数为2。所以next[i]=2；</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>FILE&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">fin</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fopen(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test.in</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">r</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>FILE&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">fout</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fopen(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test.out</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">w</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;s1[</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">],s2[</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;next[</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;max(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b)<br><img id=Codehighlighter1_181_219_Open_Image onclick="this.style.display='none'; Codehighlighter1_181_219_Open_Text.style.display='none'; Codehighlighter1_181_219_Closed_Image.style.display='inline'; Codehighlighter1_181_219_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_181_219_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_181_219_Closed_Text.style.display='none'; Codehighlighter1_181_219_Open_Image.style.display='inline'; Codehighlighter1_181_219_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_181_219_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_181_219_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(a</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">b)&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;a;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;b;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;getnext()<br><img id=Codehighlighter1_237_472_Open_Image onclick="this.style.display='none'; Codehighlighter1_237_472_Open_Text.style.display='none'; Codehighlighter1_237_472_Closed_Image.style.display='inline'; Codehighlighter1_237_472_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_237_472_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_237_472_Closed_Text.style.display='none'; Codehighlighter1_237_472_Open_Image.style.display='inline'; Codehighlighter1_237_472_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_237_472_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_237_472_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;memset(next,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(next));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;next[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">=-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">strlen(s2))<br><img id=Codehighlighter1_334_470_Open_Image onclick="this.style.display='none'; Codehighlighter1_334_470_Open_Text.style.display='none'; Codehighlighter1_334_470_Closed_Image.style.display='inline'; Codehighlighter1_334_470_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_334_470_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_334_470_Closed_Text.style.display='none'; Codehighlighter1_334_470_Open_Image.style.display='inline'; Codehighlighter1_334_470_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_334_470_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_334_470_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_370_437_Open_Image onclick="this.style.display='none'; Codehighlighter1_370_437_Open_Text.style.display='none'; Codehighlighter1_370_437_Closed_Image.style.display='inline'; Codehighlighter1_370_437_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_370_437_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_370_437_Closed_Text.style.display='none'; Codehighlighter1_370_437_Open_Image.style.display='inline'; Codehighlighter1_370_437_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">s2[i]</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">s2[j])</span><span id=Codehighlighter1_370_437_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_370_437_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;&nbsp;&nbsp;j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next[j]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">i;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">next[i];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;KMP()<br><img id=Codehighlighter1_485_696_Open_Image onclick="this.style.display='none'; Codehighlighter1_485_696_Open_Text.style.display='none'; Codehighlighter1_485_696_Closed_Image.style.display='inline'; Codehighlighter1_485_696_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_485_696_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_485_696_Closed_Text.style.display='none'; Codehighlighter1_485_696_Open_Image.style.display='inline'; Codehighlighter1_485_696_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_485_696_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_485_696_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,len1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strlen(s1),len2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strlen(s2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">((i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">len1)</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">len2))<br><img id=Codehighlighter1_570_643_Open_Image onclick="this.style.display='none'; Codehighlighter1_570_643_Open_Text.style.display='none'; Codehighlighter1_570_643_Closed_Image.style.display='inline'; Codehighlighter1_570_643_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_570_643_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_570_643_Closed_Text.style.display='none'; Codehighlighter1_570_643_Open_Image.style.display='inline'; Codehighlighter1_570_643_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_570_643_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_570_643_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_604_613_Open_Image onclick="this.style.display='none'; Codehighlighter1_604_613_Open_Text.style.display='none'; Codehighlighter1_604_613_Closed_Image.style.display='inline'; Codehighlighter1_604_613_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_604_613_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_604_613_Closed_Text.style.display='none'; Codehighlighter1_604_613_Open_Image.style.display='inline'; Codehighlighter1_604_613_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">s1[i]</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">s2[j])&nbsp;</span><span id=Codehighlighter1_604_613_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_604_613_Open_Text><span style="COLOR: #000000">{j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">next[j];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">len2)&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">len2;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;index_KMP()<br><img id=Codehighlighter1_715_964_Open_Image onclick="this.style.display='none'; Codehighlighter1_715_964_Open_Text.style.display='none'; Codehighlighter1_715_964_Closed_Image.style.display='inline'; Codehighlighter1_715_964_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_715_964_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_715_964_Closed_Text.style.display='none'; Codehighlighter1_715_964_Open_Image.style.display='inline'; Codehighlighter1_715_964_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_715_964_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_715_964_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,len1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strlen(s1),len2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strlen(s2),re</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">len1</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">j</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">len2)<br><img id=Codehighlighter1_801_947_Open_Image onclick="this.style.display='none'; Codehighlighter1_801_947_Open_Text.style.display='none'; Codehighlighter1_801_947_Closed_Image.style.display='inline'; Codehighlighter1_801_947_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_801_947_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_801_947_Closed_Text.style.display='none'; Codehighlighter1_801_947_Open_Image.style.display='inline'; Codehighlighter1_801_947_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_801_947_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_801_947_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_852_861_Open_Image onclick="this.style.display='none'; Codehighlighter1_852_861_Open_Text.style.display='none'; Codehighlighter1_852_861_Closed_Image.style.display='inline'; Codehighlighter1_852_861_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_852_861_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_852_861_Closed_Text.style.display='none'; Codehighlighter1_852_861_Open_Image.style.display='inline'; Codehighlighter1_852_861_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">s1[i]</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">s2[j])&nbsp;</span><span id=Codehighlighter1_852_861_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_852_861_Open_Text><span style="COLOR: #000000">{i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">next[j];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">max(re,j);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;re;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_978_1169_Open_Image onclick="this.style.display='none'; Codehighlighter1_978_1169_Open_Text.style.display='none'; Codehighlighter1_978_1169_Closed_Image.style.display='inline'; Codehighlighter1_978_1169_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_978_1169_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_978_1169_Closed_Text.style.display='none'; Codehighlighter1_978_1169_Open_Image.style.display='inline'; Codehighlighter1_978_1169_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_978_1169_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_978_1169_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;fscanf(fin,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,s1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;=</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_1035_1153_Open_Image onclick="this.style.display='none'; Codehighlighter1_1035_1153_Open_Text.style.display='none'; Codehighlighter1_1035_1153_Closed_Image.style.display='inline'; Codehighlighter1_1035_1153_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1035_1153_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1035_1153_Closed_Text.style.display='none'; Codehighlighter1_1035_1153_Open_Image.style.display='inline'; Codehighlighter1_1035_1153_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1035_1153_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1035_1153_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fscanf(fin,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,s2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getnext();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fout,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d&nbsp;%d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,KMP(),index_KMP());<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90237.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-16 15:47 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/16/90237.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>隐式类型转换&amp;&amp; 负数的补码</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90228.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Thu, 16 Jul 2009 07:01:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90228.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90228.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90228.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90228.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90228.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;偶然看到一道C++面试题：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;foo(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_22_143_Open_Image onclick="this.style.display='none'; Codehighlighter1_22_143_Open_Text.style.display='none'; Codehighlighter1_22_143_Closed_Image.style.display='inline'; Codehighlighter1_22_143_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_22_143_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_143_Closed_Text.style.display='none'; Codehighlighter1_22_143_Open_Image.style.display='inline'; Codehighlighter1_22_143_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_22_143_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_22_143_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(a</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">puts(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;6</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">):puts(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;=6</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">puts为打印函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
&nbsp;&nbsp;&nbsp;问输出是什么？答案是输出 &gt;6。<br>&nbsp;&nbsp;&nbsp;这道题主要考察两个东西。<br>&nbsp;&nbsp;&nbsp;1.隐式类型转换：int型变量转化成unsigned int,　b成了正数．<br>&nbsp;&nbsp;&nbsp;2.负数的补码：计算机系统中的数值是以补码形式表示（存储）的。<br><br><strong>一、C++隐式类型转换<br></strong>
<p>&nbsp;&nbsp;&nbsp;C++定义了一组内置的类型对象之间的标准转换，在必要时它们被编译器隐式的应用到对象上。在算式转换保证了二元操作符，如加法或乘法的两个操作数被提升为共同的类型，然后再用它表示结果的类型。两个通用的指导原则如下：<br>&nbsp;&nbsp;&nbsp; 1、为防止精度损失，如果必要的话，类型总是被提升为较宽的类型。<br>&nbsp;&nbsp;&nbsp; 2、所有含有小于整形的有序类型的算术表达式在计算之前其类型都会被转换成整形。<br>&nbsp;&nbsp;&nbsp; 规则的定义如上面所述，这些规则定义了一个类型转换层次结构，我们从最宽的类型long double 开始，那么另一个操作数无论是什么类型都将被转换成long double .如果两个操作数千不是long double 型，那么若其中一个操作数的类型是double 型，则另一个就被转换成double 型。例如：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ival;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;fval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;dval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dval&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;fval&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;ival&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">在计算加法前fval和ival都被转换成double<br></span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 类似地，如果两个操作数都不是double型而其中一个操作float型 ，则另一个被转换成float型。例如：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;cval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ival;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;fval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cval&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;ival&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;fval&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">在计算加法前ival和cval都被转换成float</span></div>
<p>&nbsp;&nbsp;&nbsp; 否则如果两个操作数都不是3种浮点类型之一，它们一定是某种整值类型。在确定共同的目标提升类型之前，编译器将在所有小于int 的整值类型上施加一个被称为整值提升的过程。<br>&nbsp;&nbsp;&nbsp; 在进行整值提升时类型char、signed char、unsigned char和short int 都被提升为类型int 。如果机器上的类型空间足够表示所有unsigned short 型的值，这通常发生在short用半个字而int 用一个字表示的情况下，则unsigned short int 也被转换成int 否则它会被提升为unsigned int 。wchar_t和枚举类型被提升为能够表示其底层类型所有值的最小整数类型。在下列表达式中：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;cval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;found;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">enum</span><span style="COLOR: #000000">&nbsp;mumber{m1,m2,m3}mval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ulong</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cval&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ulong</span><span style="COLOR: #000000">;</span><span style="COLOR: #0000ff">ulong</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;found;&nbsp;mval&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ulong</span><span style="COLOR: #000000">;</span></div>
<p>&nbsp;&nbsp;&nbsp;在确定两个操作数被提升的公共类型之前，cval found 和mval都被提升为int 类型。<br>&nbsp;&nbsp;&nbsp; 一旦整值提升执行完毕，类型比较就又一次开始。如果一个操作数是unsigned long 型，则第二个也被转换成unsigned long 型。在上面的例子中所有被加到ulong上的3个对象都被提升为unsigned long 型。如果两个操作数类型都不是unsigned long型 而其中一个操作数是long型，则另一个也被转换成long型。例如：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;cval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;lval;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cval&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;lval;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">在计算加法前cval和1024都被提升为long型。<br></span></div>
<p>&nbsp;&nbsp;&nbsp; long类型的一般转换有一个例外。如果一个操作数是long型而另一个是unsigned int 型，那么只有机器上的long型的长度足以容纳unsigned int 的所有值时（一般来说，在32位操作系统中long型和int 型都用一长表示，所以不满足这里的假设条件），unsigned int 才会被转换为long型，否则两个操作数都被提升为unsigned long 型。若两个操作数都不是long型而其中一个是unsigned int 型，则另一个也被转换成unsigned int 型，否则两个操作数一定都是int 型。<br>&nbsp;&nbsp;&nbsp;<span style="COLOR: red">一般来说各种类型的长度关系为 long double &gt; double&nbsp;&gt; float &gt;=&nbsp; int &gt;= short &gt; char，unsigned &gt; signed 。</span><br>&nbsp;&nbsp;&nbsp; 尽管算术转换的这些规则带给你的困惑可能多于启发，但是一般的思想是尽可能地保留类型表达式中涉及到的值的精度。这下是通过把不同的类型提升到当前出现的最宽的类型实现的。<br><br><strong>二、负数的补码<br><br></strong>&nbsp;&nbsp;&nbsp;在计算机系统中，数值一律用补码来表示（存储）。&nbsp;<br>&nbsp;&nbsp;&nbsp;主要原因：使用补码，可以将符号位和其它位统一处理；同时，减法也可按加法来处理。另外，两个用补码表示的数相加时，如果最高位（符号位）有进位，则进位被舍弃。&nbsp;<br>&nbsp;&nbsp;&nbsp;补码与原码的转换过程几乎是相同的。&nbsp;<br>&nbsp;&nbsp;&nbsp;数值的补码表示也分两种情况： <br>（1）正数的补码：与原码相同。&nbsp;<br>&nbsp;&nbsp;&nbsp;例如，+9的补码是00001001。 <br>（2）负数的补码：符号位为1，其余位为该数绝对值的原码按位取反；然后整个数加1。&nbsp;<br>&nbsp;&nbsp;&nbsp;例如，-7的补码：因为是负数，则符号位为&#8220;1&#8221;,整个为10000111；其余7位为-7的绝对值+7的原码0000111按位取反为1111000；再加1，所以-7的补码是11111001。&nbsp;<br>&nbsp;&nbsp;&nbsp;已知一个数的补码，求原码的操作分两种情况： <br>（1）如果补码的符号位为&#8220;0&#8221;，表示是一个正数，所以补码就是该数的原码。 <br>（2）如果补码的符号位为&#8220;1&#8221;，表示是一个负数，求原码的操作可以是：符号位为1，其余各位取反，然后再整个数加1。&nbsp;<br>&nbsp;&nbsp;&nbsp;例如，已知一个补码为11111001，则原码是10000111（-7）：因为符号位为&#8220;1&#8221;，表示是一个负数，所以该位不变，仍为&#8220;1&#8221;；其余7位1111001取反后为0000110；再加1，所以是10000111。 <br></p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90228.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-16 15:01 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/16/90228.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++中的位域（bit-filed）:一种节省空间的成员</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90211.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Thu, 16 Jul 2009 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90211.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90211.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/16/90211.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90211.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90211.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp; 有一种被称为位域（bit-field） 的特殊的类数据成员，它可以被声明用来存放特定数目的位。位域必须是有序数据类型。它可以有符号也可以无符号。例如：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_11_65_Open_Image onclick="this.style.display='none'; Codehighlighter1_11_65_Open_Text.style.display='none'; Codehighlighter1_11_65_Closed_Image.style.display='inline'; Codehighlighter1_11_65_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_11_65_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_11_65_Closed_Text.style.display='none'; Codehighlighter1_11_65_Open_Image.style.display='inline'; Codehighlighter1_11_65_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;File&nbsp;</span><span id=Codehighlighter1_11_65_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_11_65_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;modified&nbsp;:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位域&nbsp;(bit-field)</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;</span></div>
<p>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;位域标识符后面跟有一个冒号，然后是一个常量表达式指定位数。例如modified 是一个只有一位构成的位域。<br>&nbsp;&nbsp;&nbsp;在类体中相邻定义的位域，如果可能的话，它们会被放在同一个整数的连续位中，并以此提供空间压缩。例如，在下列声明中5 个位域被存储在单个unsigned int 中，它首先与位域mode 相关联。</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">typedef&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Bit;<br><img id=Codehighlighter1_37_141_Open_Image onclick="this.style.display='none'; Codehighlighter1_37_141_Open_Text.style.display='none'; Codehighlighter1_37_141_Closed_Image.style.display='inline'; Codehighlighter1_37_141_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_37_141_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_37_141_Closed_Text.style.display='none'; Codehighlighter1_37_141_Open_Image.style.display='inline'; Codehighlighter1_37_141_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;File&nbsp;</span><span id=Codehighlighter1_37_141_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_37_141_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>Bit&nbsp;mode:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>Bit&nbsp;modified:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>Bit&nbsp;prot_owner:&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>Bit&nbsp;prot_group:&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>Bit&nbsp;prot_world:&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<span style="COLOR: red">位域在内存中的位置是从低位向高位放置的，比如mode在Bit的最低两位（二进制数0b0000000000000011中两个1的位置）。</span><br>&nbsp;&nbsp;&nbsp;对于位域的访问方式与其他类数据成员相同。例如，类的私有位域只能在类的成员函数和友元中被访问：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;File::write()<br><img id=Codehighlighter1_19_42_Open_Image onclick="this.style.display='none'; Codehighlighter1_19_42_Open_Text.style.display='none'; Codehighlighter1_19_42_Closed_Image.style.display='inline'; Codehighlighter1_19_42_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_19_42_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_19_42_Closed_Text.style.display='none'; Codehighlighter1_19_42_Open_Image.style.display='inline'; Codehighlighter1_19_42_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_19_42_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_19_42_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>modified&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;File::close()<br><img id=Codehighlighter1_63_93_Open_Image onclick="this.style.display='none'; Codehighlighter1_63_93_Open_Text.style.display='none'; Codehighlighter1_63_93_Closed_Image.style.display='inline'; Codehighlighter1_63_93_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_63_93_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_63_93_Closed_Text.style.display='none'; Codehighlighter1_63_93_Open_Image.style.display='inline'; Codehighlighter1_63_93_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_63_93_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_63_93_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;modified&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">&nbsp;内容从略</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span></div>
<p>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;下面的例子说明了怎样使用大于1 位的位域<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_5_29_Open_Image onclick="this.style.display='none'; Codehighlighter1_5_29_Open_Text.style.display='none'; Codehighlighter1_5_29_Closed_Image.style.display='inline'; Codehighlighter1_5_29_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_5_29_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_5_29_Closed_Text.style.display='none'; Codehighlighter1_5_29_Open_Image.style.display='inline'; Codehighlighter1_5_29_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">enum</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_5_29_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_5_29_Open_Text><span style="COLOR: #000000">{&nbsp;READ&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">01</span><span style="COLOR: #000000">,&nbsp;WRITE&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">02</span><span style="COLOR: #000000">&nbsp;}</span></span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;文件模式</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_51_154_Open_Image onclick="this.style.display='none'; Codehighlighter1_51_154_Open_Text.style.display='none'; Codehighlighter1_51_154_Closed_Image.style.display='inline'; Codehighlighter1_51_154_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_51_154_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_51_154_Closed_Text.style.display='none'; Codehighlighter1_51_154_Open_Image.style.display='inline'; Codehighlighter1_51_154_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()&nbsp;</span><span id=Codehighlighter1_51_154_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_51_154_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>File&nbsp;myFile;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>myFile.mode&nbsp;</span><span style="COLOR: #000000">|=</span><span style="COLOR: #000000">&nbsp;READ;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;myFile.mode&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;READ&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">myFile.mode&nbsp;is&nbsp;set&nbsp;to&nbsp;READ\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;通常情况下我们会定义一组inline 成员函数，来测试每个位域成员的值。例如，类File可以定义成员isRead()和isWrite()<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_26_48_Open_Image onclick="this.style.display='none'; Codehighlighter1_26_48_Open_Text.style.display='none'; Codehighlighter1_26_48_Closed_Image.style.display='inline'; Codehighlighter1_26_48_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_26_48_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_26_48_Closed_Text.style.display='none'; Codehighlighter1_26_48_Open_Image.style.display='inline'; Codehighlighter1_26_48_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">inline&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;File::isRead()&nbsp;</span><span id=Codehighlighter1_26_48_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_26_48_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;mode&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;READ;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_77_100_Open_Image onclick="this.style.display='none'; Codehighlighter1_77_100_Open_Text.style.display='none'; Codehighlighter1_77_100_Closed_Image.style.display='inline'; Codehighlighter1_77_100_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_77_100_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_77_100_Closed_Text.style.display='none'; Codehighlighter1_77_100_Open_Image.style.display='inline'; Codehighlighter1_77_100_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>inline&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;File::isWrite()&nbsp;</span><span id=Codehighlighter1_77_100_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_77_100_Open_Text><span style="COLOR: #000000">{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;mode&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;WRITE;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_125_133_Open_Image onclick="this.style.display='none'; Codehighlighter1_125_133_Open_Text.style.display='none'; Codehighlighter1_125_133_Closed_Image.style.display='inline'; Codehighlighter1_125_133_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_125_133_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_125_133_Closed_Text.style.display='none'; Codehighlighter1_125_133_Open_Image.style.display='inline'; Codehighlighter1_125_133_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;myFile.isRead()&nbsp;)&nbsp;</span><span id=Codehighlighter1_125_133_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id=Codehighlighter1_125_133_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">&nbsp;</span><span style="COLOR: #008000">*/</span></span></div>
<p><br>&nbsp;&nbsp;&nbsp;有了这些成员函数，现在位域可以被声明为类File 的私有成员。<br>&nbsp;&nbsp;&nbsp;<span style="COLOR: red">由于取地址操作符&amp; 不能被应用在位域上，所以也没有能指向类的位域的指针。位域也不能是类的静态成员。</span><br>&nbsp;&nbsp;&nbsp;C++标准库提供了一个bitset 类模板，它可以辅助操纵位的集合。在可能的情况下应尽可能使用它来取代位域。</p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90211.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-16 11:50 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/16/90211.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>英语中浊化、连读、弱化、爆破的规则</title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/14/90017.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Tue, 14 Jul 2009 06:00:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/14/90017.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/90017.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/14/90017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/90017.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/90017.html</trackback:ping><description><![CDATA[<p><span><font color=#3366ff>英语中浊化、连读、弱化、爆破的规则是怎样的？何时弱化、何时浊化、何时连读、何时爆破？</font> </span></p>
<p>&nbsp;</p>
<p><span>我们都有过这样沮丧的经验，很容易听懂中国人说的英语，但是同样的对话一到英美人的嘴里，便觉得很难跟上，有时甚至是不知所云。这主要是因为我们说的英语通常单词之间很清晰，词与词之间有明显的pause, 但是英美人的口语会有很多音变，这些音变使得我们很熟悉的单词的发音变得陌生，难懂，给我们的听力造成了很大的困难，因此了解并使用各音变规则会帮助我们提高听力，使我们的发音更加地道。 <br>音变主要有 连读、失音、弱化、浊化、同化、重音、缩读等形式。这些形式的产生可以归结为一个原则，即 &#8220;Economy&#8221; —&#8220;经济&#8221;原则 或称为&#8220;省力&#8221;原则。我的语言学老师说，他曾一度为选择的研究方向为语言学而懊悔，因为那时他认为语言学既枯燥又不实用，但这一省力原则却化解了他所有的苦恼，并让他为语言学着迷。因为 &#8220;省力&#8221;这两个简单的字眼可以解释几乎所有的音变现象，人是很懒的,对于最经常的行为——说话，当然要想许多省事的法子，于是也就产生了多种为省力而衍变的音变现象。牢记省力原则，在我们读英语的时候，让自己的唇舌处于放松的状态，轻松的去读英语，我想发音的感觉一定会有所不同。 <br>言归正题, 以下列出给听力造成很大障碍的五种音变现象及其读音规则，以及最后一项关于节奏的小文章，希望能有所帮助！<br>&nbsp;<br>一、 连读 <br>连读有两种规则，分别为： <br>1、 以辅音结尾的单词+元音开头的单词：要连读 <br>如：I&#8217;d li(ke a)nother bow(l o)f rice. <br>这里like / laik / 以辅音结尾，another 以元音开头，所以连读 <br>注意： <br>以辅音结尾 指的是音标中的最后一个音是辅音，而不是单词的结尾，这如同u[ju:.]niversity前面的定冠词必须用a 一样。 <br>2、以辅音结尾的单词 + h开头的单词h不发音，与前面的辅音 <br>what wil(l he) [wili]do? <br>Ha(s he) done it before? <br>Mus(t he) [ti] go? <br>Can he do it? <br>Should he&#8230;.? <br>Tell him to ask her&#8230;. <br>Lea(ve him) [vim]. <br>For him (连读这个词，会发现和forum 很相似) <br>我第一次知道这一连读规则时，兴奋不已，很容易的听懂了许多以前觉得很难以理解的句子， <br>并且按照这种连读方式发音省力、轻松了许多。再次证实&#8221;Economy&#8221;。 <br><br>二、 音的同化 <br>音的同化也是一种连读的现象，两个词之间非常平滑的过渡，导致一个音受临音影响而变化。主要是以下三种方式： <br>1、 辅音[d]与[j]相邻时，被同化为[dэ]：Would you....? <br>2、 辅音[t]与[j]相邻时，被同化为[t&#8747;]： Can&#8217;t you:。。。。？ <br>3、 辅音[s]与[j]相邻时, 被同化为[&#8747;]： Miss you <br><br>三、 失音 <br>由于失去爆破是失音的一种现象，摩擦音也会被失去，所以统称为失音。 <br>注意： <br>爆破音并不是完全失去，仍然形成阻碍，把气流堵在里面，但不爆破，直接发出相邻的辅音。 <br>规则： <br>1、 辅音爆破音或摩擦音后面跟的是爆破音、破擦音和摩擦等，前面的辅音要失去爆破。 <br>这样的例子有很多很多， 红色标注的辅音不发音： <br>Sit down: 发音再次的老师都不会发出 [t] 音 <br>Contact lens: <br>Big cake <br>Dad told me <br>Huge change <br>Good night <br><br>四、 浊化 <br>1、[S] 后面的清辅音要浊化 <br>Discussion： [k] 浊化成 [g] <br>Stand： [t] 浊化成[d] <br>Expression： [p]浊化成[b]<br>2、美音中：[t] 在单词的中间被浊化成[d] <br>如： <br>writer， 听起来和 rider 的发音几乎没有区别 <br>letter—ladder <br>out of <br>美国人和加拿大人发音为了省事，习惯清音浊化，尤其是[t]在单词的中间一定会浊化成[d]， 但英国人发音不会这样，这也是英音和美音的一大区别。 了解这一浊化原则，会给听力带来一些帮助。<br>&nbsp;<br>五、 弱读 <br>一般来说： <br>实词重读，如动词、名词、副词等； <br>虚词弱读，如介词、代词等 <br>弱读的规则一般是：元音音节弱化成 [E] 或 <br>比如说如下几个单词：for/to/some/does/of <br>查字典会发现这些词都至少有两种读音，如for: 重读时[fR:] , 弱读时 [fE] <br><br>六、 节奏 <br>对于英语的节奏，我也把握不好，而且还为此郁闷不已。在我认为，中国人说普通话，一个句子的标准节奏和语调往往只有一个，我想英语也应该是这样，但是怎么样才是标准语调呢？特意为这个问题问过英语老师，不同的外国人说同一个陈述句会有不同得语调吗？她告诉我是的。不过在看了下面这段话之后，我想她可能误我了。:) <br>老外教你&#8220;杀手锏&#8221;：注意说话的节奏 <br>十年寒窗苦读英语，为谁辛苦为谁忙？当然是用来和老外&#8220;侃&#8221;喽。那外国人究竟如何看待中国人说的英语，他们说话有没有诀窍呢？记者请教了克里斯多佛&#183;汉普顿---英国驻上海总领事馆的考官协调，他也是当天演讲比赛的裁判之一。 <br>克里斯多佛一开口就指出了国人学英语最大的&#8220;软档&#8221; <br>&#8220;中国人喜欢在单词的读音上纠缠不休。尤其是年轻人，总希望自己能说一口标准的美式英语，最好是带点纽约口音的美式英语。于是，他们很努力地听广播、看电视，刻意模仿美国人的说话腔调。 <br>经过长时间的磨练，有些人的发音甚至比土生土长的美国人还地道。但是，我就算蒙着眼睛，也能轻易分辨出说话的是中国人，还是美国人。因为中国人说英语没有节奏。&#8221; <br>克里斯多佛所说的节奏并不仅指说话的速度快慢，还包含了许多平时不被重视的小环节，比如语调的升降、词语的重音、句子在何处停顿。中学的中文语文书中倒是有过断句练习，可几乎所有的英语教科书里都没有类似的章节，也鲜有老师会教学生这一套。所以，大多人不知道，英语句子也有自己拆分的规则。发言者要么按照中文的思维习惯，随心所欲把句子&#8220;大卸八块&#8221;；要么练习肺活量，一句话从头连到尾不喘气。于是，中国人听起来清清楚楚的句子，到外国人耳朵里就变成了&#8220;不知所云&#8221;。 <br>要改变这个习惯也不难。克里斯多佛认为，只要连续练习几个月，一个英语水平普通的人也能说出漂亮的英语，甚至达到&#8220;以假乱真&#8221;的程度，和讲母语不分上下。 <br>他的练习方法很简单---找一盒老外读的标准磁带，在录音机里不停顿地播放。然后你看着文字稿，亦步亦趋地跟着他的节奏读。这时候，充分调动你的耳朵，适应外国人的语音语调，还要像个回声筒似地反映出来。久而久之，当你习惯了老外的节奏，只要具备5000个基本单词，就能应付一般的对话 </span></p>
<img src ="http://www.cppblog.com/suiaiguo/aggbug/90017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-14 14:00 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/14/90017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>日常英语1000句 </title><link>http://www.cppblog.com/suiaiguo/archive/2009/07/11/89818.html</link><dc:creator>Saga</dc:creator><author>Saga</author><pubDate>Sat, 11 Jul 2009 14:51:00 GMT</pubDate><guid>http://www.cppblog.com/suiaiguo/archive/2009/07/11/89818.html</guid><wfw:comment>http://www.cppblog.com/suiaiguo/comments/89818.html</wfw:comment><comments>http://www.cppblog.com/suiaiguo/archive/2009/07/11/89818.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/suiaiguo/comments/commentRss/89818.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/suiaiguo/services/trackbacks/89818.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1. I see． 我明白了。2. I quit! 我不干了!3. Let go! 放手!4. Me too． 我也是。5. My god! 天哪!6. No way! 不行!7. Come on． 来吧(赶快)8. Hold on． 等一等。9. I agree。 我同意。10. Not bad． 还不错。11. Not yet． 还没。12. See you． 再见。13. Shut up! ...&nbsp;&nbsp;<a href='http://www.cppblog.com/suiaiguo/archive/2009/07/11/89818.html'>阅读全文</a><img src ="http://www.cppblog.com/suiaiguo/aggbug/89818.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/suiaiguo/" target="_blank">Saga</a> 2009-07-11 22:51 <a href="http://www.cppblog.com/suiaiguo/archive/2009/07/11/89818.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>