C++程序入門——表達(dá)式講解
在C++中,所有的代碼都是通過標(biāo)識符(Identifier)、表達(dá)式(Expression)和語句(Statement)及一些必要的符號(如大括號等)組成,在此先說明何謂標(biāo)識符。 **標(biāo)識符** 標(biāo)識符是一個字母序列,由大小寫英文字母、下劃線及數(shù)字組成,用于標(biāo)識。標(biāo)識就是標(biāo)出并識別,也就是名字。
其可以作為后面將提到的變量或者函數(shù)或者類等的名字,也就是說用來標(biāo)識某個特定的變量或者函數(shù)或者類等C++中的元素。 比如:abc就是一個合法的標(biāo)識符,即abc可以作為變量、函數(shù)等元素的名字,但并不代表abc就是某個變量或函數(shù)的名字,而所謂的合法就是任何一個標(biāo)識符都必須不能以數(shù)字開頭,只能包括大小寫英文字母、下劃線及數(shù)字,不能有其它符號,如,!^等,并且不能與C++關(guān)鍵字相同。
也就是我們在給一個變量或函數(shù)起名字的時候,必須將起的名字看作是一個標(biāo)識符,并進(jìn)而必須滿足上面提出的要求。如12ab_C就不是一個合法的標(biāo)識符,因此我們不能給某個變量或函數(shù)起12ab_C這樣的名字;ab_12C就是合法的標(biāo)識符,因此可以被用作變量或函數(shù)的名字。
C++程序入門——表達(dá)式講解 前面提到關(guān)鍵字,在后續(xù)的語句及一些聲明修飾符的介紹中將發(fā)現(xiàn),C++提供了一些特殊的標(biāo)識符作為語句的名字,用以標(biāo)識某一特定語句,如if、while等;或者提供一些修飾符用以修飾變量、函數(shù)等元素以實現(xiàn)語義或給編譯器及連接器提供一些特定信息以進(jìn)行優(yōu)化、查錯等操作,如extern、static等。
因此在命名變量或函數(shù)或其他元素時,不能使用if、extern等這種C++關(guān)鍵字作為名字,否則將導(dǎo)致編譯器無法確認(rèn)是一個變量(或函數(shù)或其它C++元素)還是一條語句,進(jìn)而無法編譯。 如果要讓某個標(biāo)識符是特定變量或函數(shù)或類的名字,就需要使用聲明,在后續(xù)的文章中再具體說明。 數(shù)字 C++作為電腦編程語言,電腦是處理數(shù)字的,因此C++中的基礎(chǔ)東西就是數(shù)字。
C++中提供兩種數(shù)字:整型數(shù)和浮點數(shù),也就是整數(shù)和小數(shù)。但由于電腦實際并不是想象中的數(shù)字化的(詳情參見《C++從零開始(三)》中的類型一節(jié)),所以整型數(shù)又分成了有符號和無符號整型數(shù),而浮點數(shù)則由精度的區(qū)別而分成單精度和雙精度浮點數(shù),同樣的整型數(shù)也根據(jù)長度分成長整型和短整型。
要在C++代碼中表示一個數(shù)字,直接書寫數(shù)字即可,如:123、34.23、-34.34等。由于電腦并非以數(shù)字為基礎(chǔ)而導(dǎo)致了前面數(shù)字的分類,為了在代碼中表現(xiàn)出來,C++提供了一系列的后綴進(jìn)行表示,如下: u或U 表示數(shù)字是無符號整型數(shù),如:123u,但并不說明是長整型還是短整型 l或L 表示數(shù)字是長整型數(shù),如:123l;而123ul就是無符號長整型數(shù);而34.4l就是長雙精度浮點數(shù),等效于雙精度浮點數(shù) i64或I64 表示數(shù)字是長長整型數(shù),其是為64位操作系統(tǒng)定義的,長度比長整型數(shù)長。
如:43i64 f或F 表示數(shù)字是單精度浮點數(shù),如:12.3f e或E 表示數(shù)字的次冪,如:34.4e-2就是0.344;0.2544e3f表示一個單精度浮點數(shù),值為254.4 當(dāng)什么后綴都沒寫時,則根據(jù)有無小數(shù)點及位數(shù)來決定其具體類型,如:123表示的是有符號整型數(shù),而12341434則是有符號長整型數(shù);而34.43表示雙精度浮點數(shù)。
為什么要搞這么多事出來,還分什么有符號無符號之類的?這全是因為電腦并非基于數(shù)字的,而是基于狀態(tài)的,詳情在下篇中將詳細(xì)說明。 作為科學(xué)計算,可能經(jīng)常會碰到使用非十進(jìn)制數(shù)字,如16進(jìn)制、8進(jìn)制等,C++也為此提供了一些前綴以進(jìn)行支持。 在數(shù)字前面加上0x或0X表示這個數(shù)字是16進(jìn)制表示的,如:0xF3Fa、0x11cF。
而在前面加一個0則表示這個數(shù)字是用8進(jìn)制表示的,如:0347,變?yōu)槭M(jìn)制數(shù)就為231。但16進(jìn)制和8進(jìn)制都不能用于表示浮點數(shù),只能表示整型數(shù),即0x34.343是錯誤的。 **字符串** C++除了提供數(shù)字這種最基礎(chǔ)的表示方式外,還提供了字符及字符串。這完全只是出于方便編寫程序而提供的,C++作為電腦語言,根本沒有提供字符串的必要性。不過由于人對電腦的基本要求就是顯示結(jié)果,而字符和字符串都由于是人易讀的符號而被用于顯示結(jié)果,所以C++專門提供了對字符串的支持。 前面說過,電腦只認(rèn)識數(shù)字,而字符就是文字符號,是一種圖形符號。
為了使電腦能夠處理符號,必須通過某種方式將符號變成數(shù)字,在電腦中這通過在符號和數(shù)字之間建立一個映射來實現(xiàn),也就是一個表格。表格有兩列,一列就是我們欲顯示的圖形符號,而另一列就是一個數(shù)字,通過這么一張表就可以在圖形符號和數(shù)字之間建立映射。
現(xiàn)在已經(jīng)定義出一標(biāo)準(zhǔn)表,稱為ASCII碼表,幾乎所有的電腦硬件都支持這個轉(zhuǎn)換表以將數(shù)字變成符號進(jìn)而顯示計算結(jié)果。 有了上面的表,當(dāng)想說明結(jié)果為“A”時,就查ASCII碼表,得到“A”這個圖形符號對應(yīng)的數(shù)字是65,然后就告訴電腦輸出序號為65的字符,最后屏幕上顯示“A”。
這明顯地繁雜得異常,為此C++就提供了字符和字符串。當(dāng)我們想得到某一個圖形符號的ASCII碼表的序號時,只需通過單引號將那個字符括起來即可,如:'A',其效果和65是一樣的。當(dāng)要使用不止一個字符時,則用雙引號將多個字符括起來,也就是所謂的字符串了,如:"ABC"。因此字符串就是多個字符連起來而已。但根據(jù)前面的說明易發(fā)現(xiàn),字符串也需要映射成數(shù)字,但它的映射就不像字符那么簡單可以通過查表就搞定的,對于此,將在后續(xù)文章中對數(shù)組作過介紹后再說明。
操作符** 電腦的基本是數(shù)字,那么電腦的所有操作都是改變數(shù)字,因此很正常地C++提供了操作數(shù)字的一些基本操作,稱作操作符(Operator),如:+ - * / 等。任何操作符都要返回一個數(shù)字,稱為操作符的返回值,因此操作符就是操作數(shù)字并返回數(shù)字的符號。作為一般性地分類,按操作符同時作用的數(shù)字個數(shù)分為一元、二元和三元操作符。 一元操作符有: + 其后接數(shù)字,原封不動地返回后接的數(shù)字。如: +4.4f的返回值是4.4;+-9.3f的返回值是-9.3。完全是出于語義的需要,如表示此數(shù)為正數(shù)。 - 其后接數(shù)字,將后接的數(shù)字的符號取反。如: -34.4f的返回值是-34.4;-(-54)的返回值是54。
用于表示負(fù)數(shù)。 ! 其后接數(shù)字,邏輯取反后接的數(shù)字。邏輯值就是“真”或“假”,為了用數(shù)字表示邏輯值,在 C++中規(guī)定,非零值即為邏輯真,而零則為邏輯假。
因此3、43.4、'A'都表示邏輯真,而0則表示邏輯假。邏輯值被應(yīng)用于后續(xù)的判斷及循環(huán)語句中。而邏輯取反就是先判斷“!”后面接的數(shù)字是邏輯真還是邏輯假,然后再將相應(yīng)值取反。如: !5的返回值是0,因為先由5非零而知是邏輯真,然后取反得邏輯假,故最后返回0。 !!345.4的返回值是1,先因345.4非零得邏輯真,取反后得邏輯假,再取反得邏輯真。雖然只要非零就是邏輯真,但作為編譯器返回的邏輯真,其一律使用1來代表邏輯真。
其后接數(shù)字,取反后接的數(shù)字。取反是邏輯中定義的操作,不能應(yīng)用于數(shù)字。為了對數(shù)字應(yīng)用取反操作,電腦中將數(shù)字用二進(jìn)制表示,然后對數(shù)字的每一位進(jìn)行取反操作(因為二進(jìn)制數(shù)的每一位都只能為1或0,正好符合邏輯的真和假)。如~123的返回值就為-124。先將123轉(zhuǎn)成二進(jìn)制數(shù)01111011,然后各位取反得10000100,最后得-124。
這里的問題就是為什么是8位而不是16位二進(jìn)制數(shù)。因為123小于128,被定位為char類型,故為8位(關(guān)于char是什么將下篇介紹)。如果是~123ul,則返回值為4294967172。 為什么要有數(shù)字取反這個操作?因為CPU提供了這樣的指令。并且其還有著很不錯且很重要的應(yīng)用,后面將介紹。 關(guān)于其他的一元操作符將在后續(xù)文章中陸續(xù)提到(但不一定全部提到)。 **二元操作符有:** +-*/% 其前后各接一數(shù)字,返回兩數(shù)字之和、差、積、商、余數(shù)。
如:34+4.4f的返回值是38.4;3+-9.3f的返回值是-6.3。34-4的返回值是30;5-234的返回值是-229。3*2的返回值是6;10/3的返回值是3。10%3的返回值是1;20%7的返回值是6。
&&|| 其前后各接一邏輯值,返回兩邏輯值之“與”運(yùn)算邏輯值和“或”運(yùn)算邏輯值。
如:'A'&&34.3f的返回值是邏輯真,為1;34&&0的返回值是邏輯假,為0。
0||'B'的返回值是邏輯真,為 1;0||0的返回值是邏輯假,為0。
&|^ 其前后各接一數(shù)字,返回兩數(shù)字之“與”運(yùn)算、“或”運(yùn)算、“異或”運(yùn)算值。
如前面所說,先將兩側(cè)的數(shù)字轉(zhuǎn)成二進(jìn)制數(shù),然后對各位進(jìn)行與、或、異或操作。如:4&6的返回值是4,4轉(zhuǎn)為00000100,6轉(zhuǎn)為00000110各位相與得,00000100,為4。
4|6的返回值是6,4轉(zhuǎn)為00000100,6轉(zhuǎn)為00000110各位相或得,00000110,為6。
4^6的返回值是2,4轉(zhuǎn)為00000100,6轉(zhuǎn)為00000110各位相異或得,00000010,為2。 >=34的返回值是0,為邏輯假;32=23和23>=14的返回值都是1,為邏輯真;54>>與>2的返回值就是00000001,為1。 左移和右移有什么用?用于一些基于二進(jìn)制數(shù)的算法,不過還可以順便作為一個簡單的優(yōu)化手段??紤]十進(jìn)制數(shù)3524,我們將它左移2位,變成352400,比原數(shù)擴(kuò)大了100倍,準(zhǔn)確的說應(yīng)該是擴(kuò)大了10的2次方倍。如果將3524右移2位,變成35,相當(dāng)于原數(shù)除以100的商。
同樣,前面4>>2,等效于4/4的商;32>>3相當(dāng)于32/8,即相當(dāng)于32除以2的3次方的商。而4?:。它的返回值為:如果是邏輯真,返回,否則返回。如: 34?4:2的返回值就是4,因為34非零,為邏輯真,返回4。而0?4:2的返回值就是2,因為0為邏輯假,返回2。 **表達(dá)式** 你應(yīng)該發(fā)現(xiàn)前面的荒謬之處了——12>435返回值為0,那為什么不直接寫0還吃飽了撐了寫個12>435在那?這就是表達(dá)式的意義了。 前面說“>”的前后各接一數(shù)字,但是操作符是操作數(shù)字并返回數(shù)字的符號,因為它返回數(shù)字,因此可以放在上面說的任何一個要求接數(shù)字的地方,也就形成了所謂的表達(dá)式。
如:23*54/45>34的返回值就是0,因為23*54的返回值為1242;然后又將1242作為“/”的左接數(shù)字,得到新的返回值27.6;最后將27.6作為“>”的左接數(shù)字進(jìn)而得到返回值0,為邏輯假。 因此表達(dá)式就是由一系列返回數(shù)字的東西和操作符組合而成的一段代碼,其由于是由操作符組成的,故一定返回值。而前面說的“返回數(shù)字的東西”則可以是另一個表達(dá)式,或者一個變量,或者一個具有返回值的函數(shù),或者具有數(shù)字類型操作符重載的類的對象等,反正只要是能返回一個數(shù)字的東西。如果對于何謂變量、函數(shù)、類等這些名詞感到陌生,不需要去管它們,在后繼的文章中將會一一說明。 因此34也是一個表達(dá)式,其返回值為34,只不過是沒有操作符的表達(dá)式罷了(在后面將會了解到34其實是一種操作符)。故表達(dá)式的概念其實是很廣的,只要有返回值的東西就可以稱為表達(dá)式。 由于表達(dá)式里有很多操作符,執(zhí)行操作符的順序依賴于操作符的優(yōu)先級,就和數(shù)學(xué)中的一樣,*、/的優(yōu)先級大于+、-,而+、-又大于>、<等邏輯操作符。不用去刻意記住操作符的優(yōu)先級,當(dāng)不能確定操作符的執(zhí)行順序時,可以使用小括號來進(jìn)行指定。
如: ((1+2)*3)+3)/4的返回值為3,而1+2*3+3/4的返回值為7。注意3/4為0,因為3/4的商是0。當(dāng)希望進(jìn)行浮點數(shù)除法或乘法時,只需讓操作數(shù)中的某一個為浮點數(shù)即可,如:3/4.0的返回值為0.75。
& | ^ ~等的應(yīng)用 前面提過邏輯操作符“&&”、“||”、“!”等,作為表示邏輯,其被C++提供一點都不值得驚奇。但是為什么要有一個將數(shù)字轉(zhuǎn)成二進(jìn)制數(shù),然后對二進(jìn)制數(shù)的各位進(jìn)行邏輯操作的這么一類操作符呢?首先是CPU提供了相應(yīng)的指令,并且其還有著下面這個非常有意義的應(yīng)用。 考慮一十字路口,每個路口有三盞紅綠燈,分別指明能否左轉(zhuǎn)、右轉(zhuǎn)及直行。
共有12盞,現(xiàn)在要為它編寫一個控制程序,不管這程序的功能怎樣,首先需要將紅綠燈的狀態(tài)轉(zhuǎn)化為數(shù)字,因為電腦只知道數(shù)字。所以用3個數(shù)字分別表示某路口的三盞紅綠燈,因此每個紅綠燈的狀態(tài)由一個數(shù)字來表示,假設(shè)紅燈為0,綠燈為1(不考慮黃燈或其他情況)。
后來忽然發(fā)現(xiàn),其實也可以用一個數(shù)字表示一個路口的三盞紅綠燈狀態(tài),如用110表示左轉(zhuǎn)綠燈、直行綠燈而右轉(zhuǎn)紅燈。上面的110是一個十進(jìn)制數(shù)字,它的每一位實際都可以為0~9十個數(shù)字,但是這里只應(yīng)用到了兩個:0和1,感覺很浪費。
故選擇二進(jìn)制數(shù)來表示,還是110,但是是二進(jìn)制數(shù)了,轉(zhuǎn)成十進(jìn)制數(shù)為6,即使當(dāng)為111時轉(zhuǎn)成十進(jìn)制數(shù)也只是7,比前面的110這個十進(jìn)制數(shù)小多了,節(jié)約了……??什么?? 我們在紙上寫數(shù)字235425234一定比寫134這個數(shù)字要更多地占用紙張(假設(shè)字都一樣大)。因此記錄一個大的數(shù)比記錄一個小的數(shù)要花費更多的資源。
簡直荒謬!不管是100還是1000,都只是一個數(shù)字,為什么記錄大的數(shù)字就更費資源?因為電腦并不是數(shù)字計算機(jī),而是電子計算機(jī),它是基于狀態(tài)而不是基于數(shù)字的,這在下篇會詳細(xì)說明。
電腦必須使用某種表示方式來代表一個數(shù)字,而那個表示方式和二進(jìn)制很像,但并不是二進(jìn)制數(shù),故出現(xiàn)記錄大的數(shù)較小的數(shù)更耗資源,這也就是為什么上面整型數(shù)要分什么長整型短整型的原因了。 下面繼續(xù)上面的思考。使用了110這個二進(jìn)制數(shù)來表示三盞紅綠燈的狀態(tài),那么現(xiàn)在要知道110這個數(shù)字代表左轉(zhuǎn)紅綠燈的什么狀態(tài)。以數(shù)字的第三位表示左轉(zhuǎn),不過電腦并不知道這個,因此如下:110&100。
這個表達(dá)式的返回值是100,非零,邏輯真。假設(shè)某路口的狀態(tài)為010,則同樣的010&100,返回值為0,邏輯假。因此使用“&”操作符可以將二進(jìn)制數(shù)中的某一位或幾位的狀態(tài)提取出來。
所以我們要了解一個數(shù)字代表 的紅綠燈狀態(tài)中的左轉(zhuǎn)紅綠燈是否綠燈時,只需讓它和100相與即可。 現(xiàn)在要保持其他紅綠燈的狀態(tài)不變,僅僅使左轉(zhuǎn)紅綠燈為綠燈,如當(dāng)前狀態(tài)為010,為了使左轉(zhuǎn)紅綠燈為綠燈,值應(yīng)該為110,這可以通過010|100做到。
如果當(dāng)前狀態(tài)是001,則001|100為101,正確——直行和右轉(zhuǎn)的紅綠燈狀態(tài)均沒有發(fā)生變化。因此使用“|”操作符可以給一個二進(jìn)制數(shù)中的某一位或幾位設(shè)置狀態(tài),但只能設(shè)置為1,如果想設(shè)置為0,如101,要關(guān)掉左轉(zhuǎn)的綠燈,則101&~100,返回值為001。
上面一直提到的路口紅綠燈的狀態(tài)實際編寫時可以使用一個變量來表示,而上面的100也可以用一個標(biāo)識符來表示,如state&TS_LEFT,就可以表示檢查變量state所表示的狀態(tài)中的左轉(zhuǎn)紅綠燈的狀態(tài)。 上面的這種方法被大量地運(yùn)用,如創(chuàng)建一個窗口,一個窗口可能有二三十個風(fēng)格,則通過上面的方法,就可以只用一個32位長的二進(jìn)制數(shù)字就表示了窗口的風(fēng)格,而不用去弄二三十個數(shù)字來分別代表每種風(fēng)格是否具有。
聲明:免責(zé)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),也不承認(rèn)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,請發(fā)
送郵件至:operations@xinnet.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,本站將立刻刪除涉嫌侵權(quán)內(nèi)容。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時
需注明出處:新網(wǎng)idc知識百科