C++編程基礎(chǔ)之賦值操作符

字號:

對于變量最關(guān)鍵的東西卻由于篇幅限制而沒有說明,下面先說明如何訪問內(nèi)存。
    賦值語句
    前面已經(jīng)說明,要訪問內(nèi)存,就需要相應(yīng)的地址以表明訪問哪塊內(nèi)存,而變量是一個映射,因此變量名就相當于一個地址。對于內(nèi)存的操作,在一般情況下就只有讀取內(nèi)存中的數(shù)值和將數(shù)值寫入內(nèi)存(不考慮分配和釋放內(nèi)存),在C++中,為了將一數(shù)值寫入某變量對應(yīng)的地址所標識的內(nèi)存中(出于簡便,以后稱變量a對應(yīng)的地址為變量a的地址,而直接稱變量a的地址所標識的內(nèi)存為變量a),只需先書寫變量名,后接“=”,再接欲寫入的數(shù)字(關(guān)于數(shù)字,請參考《C++從零開始(二)》)以及分號。如下:
    a = 10.0f; b = 34;
    由于接的是數(shù)字,因此就可以接表達式并由編譯器生成計算相應(yīng)表達式所需的代碼,也就可如下:
    c = a / b * 120.4f;
    上句編譯器將會生成進行除法和乘法計算的CPU指令,在計算完畢后(也就是求得表達式a / b * 120.4f的值了后),也會同時生成將計算結(jié)果放到變量c中去的CPU指令,這就是語句的基本作用(對于語句,在《C++從零開始(六)》中會詳細說明)。
    上面在書寫賦值語句時,應(yīng)該確保此語句之前已經(jīng)將使用到的變量定義過,這樣編譯器才能在生成賦值用的CPU指令時查找到相應(yīng)變量的地址,進而完成CPU指令的生成。如上面的a和b,就需要在書寫上面語句前先書寫類似下面的變量定義:
    float a; long b;
    直接書寫變量名也是一條語句,其導(dǎo)致編譯器生成一條讀取相應(yīng)變量的內(nèi)容的語句。即可以如下書寫:
    a;
    上面將生成一條讀取內(nèi)存的語句,即使從內(nèi)存中讀出來的數(shù)字沒有任何應(yīng)用(當然,如果編譯器開了優(yōu)化選項,則上面的語句將不會生成任何代碼)。從這一點以及上面的c = a / b * 120.4f;語句中,都可以看出一點——變量是可以返回數(shù)字的而變量返回的數(shù)字就是按照變量的類型來解釋變量對應(yīng)內(nèi)存中的內(nèi)容所得到的數(shù)字。這句話也許不是那么容易理解,在看過后面的類型轉(zhuǎn)換一節(jié)后應(yīng)該就可以理解了。
    因此為了將數(shù)據(jù)寫入一塊內(nèi)存,使用賦值語句(即等號);要讀取一塊內(nèi)存,書寫標識內(nèi)存的變量名。所以就可以這樣書寫:a = a + 3;
    假設(shè)a原來的值為1,則上面的賦值語句將a的值取出來,加上3,得到結(jié)果4,將4再寫入a中去。由于C++使用“=”來代表賦值語句,很容易使人和數(shù)學(xué)中的等號混淆起來,這點應(yīng)注意。
    而如上的float a;語句,當還未對變量進行任何賦值操作時,a的值是什么?上帝才知道。當時的a的內(nèi)容是什么(對于VC編譯器,在開啟了調(diào)試選項時,將會用0xCCCCCCCC填充這些未初始化內(nèi)存),就用IEEE的real*4格式來解釋它并得到相應(yīng)的一個數(shù)字,也就是a的值。因此應(yīng)在變量定義的時候就進行賦值(但是會有性能上的影響,不過很?。猿跏蓟兞慷乐钩霈F(xiàn)莫名其妙的值,如:float a = 0.0f;。
    賦值操作符
    上面的a = a + 3;的意思就是讓a的值增加3。在C++中,對于這種情況給出了一種簡寫方案,即前面的語句可以寫成:a += 3;。應(yīng)當注意這兩條語句從邏輯上講都是使變量a的值增3,但是它們實際是有區(qū)別的,后者可以被編譯成優(yōu)化的代碼,因為其意思是使某一塊內(nèi)存的值增加一定數(shù)量,而前者是將一個數(shù)字寫入到某塊內(nèi)存中。所以如果可能,應(yīng)盡量使用后者,即a += 3;。這種語句可以讓編譯器進行一定的優(yōu)化(但由于現(xiàn)在的編譯器都非常智能,能夠發(fā)現(xiàn)a = a + 3;是對一塊內(nèi)存的增值操作而不是一塊內(nèi)存的賦值操作,因此上面兩條語句實際上可以認為完全相同,僅僅只具有簡寫的功能了)。
    對于上面的情況,也可以應(yīng)用在減法、乘法等二元非邏輯操作符(不是邏輯值操作符,即不能a &&= 3;)上,如:a *= 3; a -= 4; a  = 34; a >>= 3;等。
    除了上面的簡寫外,C++還提供了一種簡寫方式,即a++;,其邏輯上等同于a += 1;。同上,在電腦編程中,加一和減一是經(jīng)常用到的,因此CPU專門提供了兩條指令來進行加一和減一操作(轉(zhuǎn)成匯編語言就是Inc和Dec),但速度比直接通過加法或減法指令來執(zhí)行要快得多。為此C++中也就提供了“++”和“—”操作符來對應(yīng)Inc和Dec。所以a++;雖然邏輯上和a = a + 1;等效,實際由于編譯器可能做出的優(yōu)化處理而不同,但還是如上,由于編譯器的智能化,其是有可能看出a = a + 1;可以編譯成Inc指令進而即使沒有使用a++;卻也依然可以得到優(yōu)化的代碼,這樣a++;將只剩下簡寫的意義而已。
    應(yīng)當注意一點,a = 3;這句語句也將返回一個數(shù)字,也就是在a被賦完值后a的值。由于其可以返回數(shù)字,按照《C++從零開始(二)》中所說,“=”就屬于操作符,也就可以如下書寫:
    c = 4 + ( a = 3 );
    之所以打括號是因為“=”的優(yōu)先級較“+”低,而更常見和正常的應(yīng)用是:c = a = 3;
    應(yīng)該注意上面并不是將c和a賦值為3,而是在a被賦值為3后再將a賦值給c,雖然最后結(jié)果和c、a都賦值為3是一樣的,但不應(yīng)該這樣理解。由于a++;表示的就是a += 1;就是a = a + 1;,因此a++;也將返回一個數(shù)字。也由于這個原因,C++又提供了另一個簡寫方式,++a;。
    假設(shè)a為1,則a++;將先返回a的值,1,然后再將a的值加一;而++a;先將a的值加一,再返回a的值,2。而a—和—a也是如此,只不過是減一罷了。
    上面的變量a按照最上面的變量定義,是float類型的變量,對它使用++操作符并不能得到預(yù)想的優(yōu)化,因為float類型是浮點類型,其是使用IEEE的real*4格式來表示數(shù)字的,而不是二進制原碼或補碼,而前面提到的Inc和Dec指令都是出于二進制的表示優(yōu)點來進行快速增一和減一,所以如果對浮點類型的變量運用“++”操作符,將完全只是簡寫,沒有任何的優(yōu)化效果(當然,如果CPU提供了新的指令集,如MMX等,以對real*4格式進行快速增一和減一操作,且編譯器支持相應(yīng)指令集,則還是可以產(chǎn)生優(yōu)化效果的)。