表達(dá)式求值的過程中,往往會伴隨著數(shù)據(jù)類型的自動轉(zhuǎn)換,而數(shù)據(jù)類型的轉(zhuǎn)換的一般情況如下所示,從低到高。
long double
double
float
unsigned long int
long int
unsigned int
int
有幾點(diǎn)需要注意:
1. 這里沒有出現(xiàn)char,short,enum,因為它們會被自動轉(zhuǎn)換為int或是unsigned int類型
2. 當(dāng)unsigned int 和 int 出現(xiàn)在同一個式子中時,需要注意,如:5u – 10,結(jié)果是大于0的,不是-5,而是4294967291
3. 另外對于32位機(jī),由于long int的表現(xiàn)形式與int相同,unsigned int的表現(xiàn)形式與unsigned long int相同,因此long int的數(shù)值范圍無法包含unsigned int,因此在32位機(jī)進(jìn)行處理時,它們間的類型的自動轉(zhuǎn)換可以理解為4位的有符號自動轉(zhuǎn)為4位的無符號,然后再向上轉(zhuǎn)為float型等;如 unsigned int a = 45; long int b = 2147483643; a + b中可以理解為都轉(zhuǎn)換成了unsigned long類型
摘要:就windows下傻瓜式安裝codelite時出現(xiàn)的一些問題進(jìn)行了闡述,并提供了一定的解決方案,希望對于遇到相同情況的讀者有所幫助。
在這里不說為什么選擇codelite這么個IDE,其實這樣的爭執(zhí)在幾分鐘后往往會偏離正題,思緒被情緒控制,各執(zhí)己見,何謂?
什么是傻瓜式安裝呢,就是在windows下,利用release的安裝版本,這里下的是包含wxWidget,MinGW的安裝版本,然后根據(jù)它的指示一直下一步下一步進(jìn)行就行了。如果你的機(jī)子最初是干干凈凈的,最后安裝的程序會是成功的。但是這基本上是不可能的,而我呢,恰好由于事先在機(jī)子上裝了些東西,就使得安裝完成后并不能像codelite官網(wǎng)中quick start所說的那樣進(jìn)行操作。
想原因可能如下:
*. 原來安裝過code::block,將code::block自帶的mingw32-make.exe所在的目錄加在了環(huán)境變量中,并且原來安裝過庫wxWidget的低版本,由于選擇了codelite,于是將wxWidget原來的版本和code::block都刪除了。并在環(huán)境變量中也將值刪除了。
然后卸載掉codelite進(jìn)行重裝,不過依然不能運(yùn)行wxWidget框架程序。build時出現(xiàn)需要將“WXWIN = C:\wxWidget”的提示,查看了一下setting:tags setting : ctags : include files內(nèi)包含的竟然是perl中的mingw,額裝的東西太多了,于是將perl相關(guān)的環(huán)境變量也刪除了。
繼續(xù)重裝,結(jié)果發(fā)現(xiàn)依然沒有任何改變,悲劇,到底是怎么回事呢,細(xì)想來,原來C盤的Application Data中有codelite的配置文件,由于卸載的過程中并沒有將這些配置文件刪除,重裝后依然使用的是這些配置文件,才導(dǎo)致了問題的出現(xiàn),于是將Application Data下的codelite文件夾刪除,再進(jìn)行重裝,終于是成功了。
傻瓜式安裝,只是設(shè)想到了理想的情況下如何進(jìn)行處理,沒有料想到會出現(xiàn)想我這樣的情況,所以安裝結(jié)束后相關(guān)配置文件中的數(shù)據(jù)的設(shè)定出現(xiàn)了錯誤,導(dǎo)致無法正常build。
至此,安裝結(jié)束了,學(xué)習(xí)才剛剛開始。
也許你會說,為什么不從codelite軟件中對配置數(shù)據(jù)進(jìn)行設(shè)定呢,其實進(jìn)行了嘗試,正確的設(shè)定了ctags : include files的位置,但是結(jié)果依然無法build,出現(xiàn)類似“WXWIN = C:\wxWidget”的提示,于是將其設(shè)置到環(huán)境變量中也沒有得到相應(yīng)的解決,所以茫然之下才出此下策,一切從頭開始。
相信隨著深入的學(xué)習(xí),對于它的處理方式,配置文件的設(shè)定等,都會慢慢了解的,一鳴驚人的背后蘊(yùn)含著多少的厚積呢,急不來的。
補(bǔ)充一下:
環(huán)境變量的設(shè)置不是設(shè)置計算機(jī)的環(huán)境變量,而是設(shè)置codelite下setting下的環(huán)境變量,額,因為慣性思維沒有考慮到這點(diǎn),悲劇哦。
VIM的學(xué)習(xí)不是一天兩天的事情,先用著IDE吧,并逐步學(xué)習(xí)VIM的使用。
最近由于工作的需要,要用到界面的開發(fā),選什么庫呢,MFC,Qt or wxWidget。對微軟的東西有種莫名的反感,也許那么多年了不得不用它的產(chǎn)品,特別是操作系統(tǒng),有時特別是在安裝程序的時候,點(diǎn)著是否接受協(xié)議,不接受自然是無法安裝了,都習(xí)慣性點(diǎn)擊同意了,會剎那的感覺自己是不是被當(dāng)作了一個“低能兒”的,也許是這么一種心理的作怪,總是在矛盾中用著微軟的產(chǎn)品,想跳出使用linux,但是學(xué)習(xí)上,別人都是用office進(jìn)行操作,導(dǎo)師對于工作的檢查也都用MS office,換用linux的話會使工作進(jìn)度,交流等產(chǎn)生一定的障礙吧。很多東西就仿佛和它綁在了一起。慢慢來,一步一步將它對自己的影響逐漸降低吧,又從開源的角度考慮,選擇了wxWidget于是又選擇了codelite作為學(xué)習(xí)該庫的IDE了。自然VIM依然在不斷的進(jìn)行中。
相信微軟是無法束縛我的思維的。成為工具的主人。
總結(jié):
隨著對VIM的慢慢接觸,逐漸發(fā)現(xiàn)了它作為編輯器的強(qiáng)大,相信自己會持之以恒的。
習(xí)慣有時能夠在解決問題上節(jié)省很多的時間,但會使得一個人的敏感性降低,沒有什么東西是一塵不變的,正因為人們都在重復(fù)著一種類似的生活方式,上班,工作,回家,睡覺,繼而上班,這樣不斷的往復(fù)著,或是學(xué)習(xí)上課等,也是以一種類似的方式往復(fù)著,這樣便更加容易陷入到習(xí)慣的河流中,慢慢迷失了原有的激情,原有的對于事、對于人的敏感性。在這里并不是想要一味著貶低習(xí)慣,只是想喚醒人們心中那種不知道出現(xiàn)了多久的迷茫,喚醒覆滅已久的熱情,讓他們能夠在生活的腳步中,保持一顆清醒的頭腦,成為習(xí)慣的主人,而不是成為習(xí)慣的奴隸,并謹(jǐn)記流動著的才是真理,死寂不變的是一灘死水,今天的清澈,并不能改變未來的骯臟與渾濁。
寫給自己,也寫給大眾。
摘要:簡要比較了直接、指針、引用三中函數(shù)參數(shù)傳遞方式,并對其優(yōu)缺點(diǎn)進(jìn)行了大致的說明
1. 眾所周知,函數(shù)參數(shù)的直接傳遞就是實現(xiàn)一個拷貝值,這個拷貝值的變化,并不會改變原值的變化,因為兩個被來就是不同的個體,就好比兩個克隆的個體,雖然兩者之間有很多相同的地方,但是它們的思維是獨(dú)立的。
2. 通過指針的方式給函數(shù)參數(shù)傳值呢,從根本上來講,它仍然是直接傳值,但是這個拷貝的值比較特殊,是一個地址罷了,如:
1: void fun(int *pnValue)
2: { 3: ...;
4: }
5: int main()
6: { 7: int nValue = 6;
8: fun(&nValue);
9: }
它其實是將nValue的地址拷貝給了pnValue,如果在fun函數(shù)中,一開始就將pnValue的值給改變,如pnValue=&nValue2,那么pnValue指向的內(nèi)容的改變,將不會影響到nValue。
同時有一點(diǎn)需要注意的是,空指針對象是沒有意義的,會引起程序的奔潰,因此在開始因該進(jìn)行檢測,if(!pnValue) return;
通過指針傳參數(shù)的優(yōu)點(diǎn):
1) 允許你改變傳遞的參數(shù)的值
2) 由于它拷貝的僅僅是一個字節(jié)大小的地址,因此傳遞的過程是快速的,特別對于較大的結(jié)構(gòu)或是類
3) 我們通過這種傳參方式,獲取從函數(shù)中返回的多個量
缺點(diǎn):
1) 傳遞的只能是普通的變量,不能是字面常量或表達(dá)式
2) 所有的傳遞值都得檢查是不是空指針
3. 通過引用的方式傳遞參數(shù)
雖然在底層的操作中,通過引用也是通過“指針的方式”進(jìn)行實現(xiàn)的http://blog.csdn.net/wanwenweifly4/article/details/6739687),但是從語言上考慮,引用是對象的別名,也是一個對象,并不是指針,因為它的概念是在語言上定義的,而不是底層的實現(xiàn)方式,換一種思維,拋開所有的比匯編語言高級的語言,回到匯編語言建立初期,單單從匯編語言上考慮,那時有沒有指針的概念呢?因此應(yīng)該理性的對待引用在C++語言中的概念,也應(yīng)該冷靜的認(rèn)識它在底層中的實現(xiàn)方式,區(qū)分的對待,其實也不用爭執(zhí)于這個問題,認(rèn)清了,會用了,就成了。(這些僅個人見解,批判的看待吧)。
它在傳參中的優(yōu)點(diǎn):
1) 允許你改變傳遞的參數(shù)的值
2) 傳遞的過程是快速的,特別對于較大的結(jié)構(gòu)或是類
3) 可以通過添加一個const,避免不經(jīng)意的改變
4) 我們通過這種傳參方式,獲取從函數(shù)中返回的多個量
缺點(diǎn):
1) 非const類型的參數(shù),傳遞的只能是普通的變量,不能是字面常量或表達(dá)式
2) 不容易區(qū)分哪些變量是input,需要output,或都是
3) 通過函數(shù)的調(diào)用,很難看出那個參數(shù)是將被改變的,因為它和直接傳值的方式相同,只能通過函數(shù)原型進(jìn)行辨認(rèn),當(dāng)程序員不小心忽視的時候,可能會導(dǎo)致錯誤的發(fā)生
ps:
1: #include <iostream>
2:
3: int nFive = 5;
4: int nSix = 6;
8: void SetToSix(int *pTempPtr);
9:
10: int main()
11: { 12: using namespace std;
13:
16: int *pPtr = &nFive;
19: cout << *pPtr;
20:
23: SetToSix(pPtr);
27: cout << *pPtr;
28:
29: return 0;
30: }
31:
33: void SetToSix(int *pTempPtr)
34: { 35: using namespace std;
36:
38: pTempPtr = &nSix;
41: cout << *pTempPtr;
42: }
上面這個程序中輸出的結(jié)果是 565
如果想使得輸出的結(jié)果為566呢,有一個方法可以實現(xiàn),就是采用指針的引用,如下:
1: // pTempPtr is now a reference to a pointer to pPtr!
2: // This means if we change pTempPtr, we change pPtr!
3: void SetToSix(int *&pTempPtr)
4: { 5: using namespace std;
6:
7: pTempPtr = &nSix;
8:
9: // This will print 6
10: cout << *pTempPtr;
11: }
1. const指針總是指向相同的地址,該地址是不能被改變的.
1: int nValue = 5;
2: int *const pnPtr = &nValue;
*pnPtr = 6; 這樣的操作是可行的;而 int nValue2 = 2; pnPtr = &nValue2;這樣的操作是不可行的。
int *const pnPtr 可以這么理解,pnPtr當(dāng)作地址,該指針有const地址,并且指向一個整型變量。
2. 指向const變量(雖然這個變量本身可以不是const的)的指針
1: int nValue = 5;
2: const int *pnPtr = &nValue;
const int *pnPtr可以這么理解,一個可以改變地址的指針指向的是一個不能改變大小的變量。
也就是說,*pnPtr = 6;這樣是不行的;int nValue2 = 6; pnPtr = &nValue2;這樣是可行的
3. 當(dāng)然,還有一種就是兩者都不能改變了。
int nValue = 2;
const int *const pnPtr = &nValue;
不過此時可以通過nValue=6;來改變*pnPtr的值。把int nValue = 2;改成 const int nValue = 2;那么就什么都不能變咯。
摘要:舉了幾個動態(tài)內(nèi)存分配過程中,發(fā)生內(nèi)存泄漏的例子
1. 分配了內(nèi)存,卻沒有及時刪除,導(dǎo)致泄漏
1: void doSomething()
2: { 3: int *pnValue = new int;
4: }
2. 為指針變量分配了一個內(nèi)存,然后又讓指針變量指向其他的值,導(dǎo)致泄漏
1: int nValue = 5;
2: int *pnValue = new int;
3: pnValue = &nValue; // old address lost, memory leak results
3. 連續(xù)分配了兩次內(nèi)存,第一次分配的內(nèi)存由于沒有delete,導(dǎo)致泄漏
1: int *pnValue = new int;
2: pnValue = new int; // old address lost, memory leak results
先來看一下一段代碼:
1: char szString[255];
2: cin >> szString;
3: cout << “You entered: ”<< szString << endl;
這段代碼在c++程序中是很常見的,但仔細(xì)想一下如果你輸入的字符串長度大于255,就會出現(xiàn)溢出的現(xiàn)象,也許這個問題通常會被人忽略。
其實我們可以選擇一個更好的實現(xiàn)方法,如下
1: char szString[255];
2: cin.getline(szString, 255);
3: cout << "Your entered: " << szString << endl;
通過這樣的方式,像第一個例子中可能出現(xiàn)的內(nèi)存溢出的現(xiàn)象就可以避免了。
from http://www.learncpp.com/cpp-tutorial/59-random-number-generation/
通常在游戲,統(tǒng)計模型程序和科學(xué)模擬中會用到隨機(jī)事件。
而由于計算機(jī)的本質(zhì)結(jié)構(gòu)決定計算機(jī)只能生成偽隨機(jī)數(shù)據(jù)。
偽隨機(jī)生成器,設(shè)定一個初始值(seed),對它進(jìn)行操作形成不同的數(shù)值,讓它看上去與初始值沒有聯(lián)系。如果算法足夠復(fù)雜,將同樣的算法用到最后生成的數(shù)字,這樣就能夠產(chǎn)生一些列看上去隨機(jī)的數(shù)值。
下面是一個產(chǎn)生100個偽隨機(jī)數(shù)的程序:
1.
1: #include <stdafx.h>
2: #include <iostream>
3: using namespace std;
4:
5: unsigned int PRNG()
6: { 7: // our initial starting seed is 5323
8: static unsigned int nSeed = 5323;
9:
10: // Take the current seed and generate a new value from it
11: // Due to our use of large constants and overflow, it would be
12: // very hard for someone to predict what the next number is
13: // going to be from the previous one.
14: nSeed = (8253729 * nSeed + 2396403);
15:
16: // Take the seed and return a value between 0 and 32767
17: return nSeed % 32767;
18: }
19:
20: int main()
21: { 22: // Print 100 random numbers
23: for (int nCount=0; nCount < 100; ++nCount)
24: { 25: cout << PRNG() << "\t";
26:
27: // If we've printed 5 numbers, start a new column
28: if ((nCount+1) % 5 == 0)
29: cout << endl;
30: }
31: }
事實上我們這個例子并不是很好,但是它足夠用來說明偽隨機(jī)數(shù)是如何產(chǎn)生的。
C++產(chǎn)生偽隨機(jī)數(shù)
語言中有內(nèi)置的隨機(jī)數(shù)生成器,它需要兩個獨(dú)立的函數(shù)組合使用。
srand() 用來設(shè)置初始seed。srand()通常只調(diào)用一次。
rand()生成序列中的下一個隨機(jī)值。
2.
1: #include <iostream>
2: #include <cstdlib> // for rand() and srand()
3: using namespace std;
4:
5: int main()
6: { 7: srand(5323); // set initial seed value to 5323
8:
9: // Print 100 random numbers
10: for (int nCount=0; nCount < 100; ++nCount)
11: { 12: cout << rand() <<“\t”;
13:
14: // If we've printed 5 numbers, start a new column
15: if ((nCount+1) % 5 == 0)
16: cout << endl;
17: }
18: }
rand()產(chǎn)生的偽隨機(jī)數(shù)的范圍在0到RAND_MAX之間,通常它的值在cstdlib中為32767.
通常我們并不想要這個范圍內(nèi)的隨機(jī)值。我們想要兩個nLow和nHigh范圍內(nèi)。如1-6.
3.
1: // Generate a random number between nLow and nHigh (inclusive)
2: unsigned int GetRandomNumber(int nLow, int nHigh)
3: { 4: return (rand() % (nHigh - nLow + 1)) + nLow;
5: }
當(dāng)我們反復(fù)運(yùn)行第2個程序的時候,發(fā)現(xiàn)每次的結(jié)果都是相同的。由于我們每次設(shè)置的seed都是相同的。因此我們使用了time()函數(shù)來產(chǎn)生seed。
1: #include <stdafx.h>
2: #include <iostream>
3: #include <cstdlib> // for rand() and srand()
4: #include <ctime> // for time()
5: using namespace std;
6:
7: int main()
8: { 9:
10: srand(time(0)); // set initial seed value to system clock
11: for (int nCount=0; nCount < 100; ++nCount)
12: { 13: cout << rand() << "\t";
14:
15: if ((nCount+1) % 5 == 0)
16: cout << endl;
17: }
18: }
怎樣的偽隨機(jī)生成器算是好的呢?
1)生成器會以相同的概率產(chǎn)生每一個數(shù)值。
2)隨機(jī)序列的下一個數(shù)字不能明顯、容易被預(yù)測
3)隨機(jī)數(shù)生成器產(chǎn)生的數(shù)值有一個好的分布,忽而小,忽而大,讓人感覺是隨機(jī)的。
4)所有的偽隨機(jī)生成器都是周期性的
rand()函數(shù)只是一個普通的偽隨機(jī)生成器
大多數(shù)rand()都是使用Linear Congruential Generator方法實現(xiàn)的。
由于RAND_MAX通常是32767,意味著如果我們想要更大的范圍就會不適合了。同時,rand()也不適合產(chǎn)生浮點(diǎn)型隨機(jī)值如0.0-1.0. 同時rand()相對于其他算法擁有一個短的周期。
可以使用Mersenne Twister,它具有更好的結(jié)果,同時使用相對簡單。
from http://www.learncpp.com/cpp-tutorial/44-type-conversion-and-casting/
類型隱式轉(zhuǎn)換
類型隱式轉(zhuǎn)換的步驟如下所示:
Long double (highest)
Double
Float
Unsigned long int
Long int
Unsigned int
Int (lowest)
最底層是int而不是short或是char,是因為char和short在求值時會被擴(kuò)展為int。
隱式轉(zhuǎn)換會出現(xiàn)一些有趣的問題,如5u - 10。也許你會認(rèn)為結(jié)果是-5.但是10為int型,發(fā)生隱式轉(zhuǎn)換成unsigned int型,因此最后結(jié)果為unsigned int型,2^32 - 5。又如float fValue = 10/4;
from http://www.learncpp.com/cpp-tutorial/38-bitwise-operators/
前面的文章在 http://www.cnblogs.com/grass-and-moon/
位操作符的由來主要是為了更充分的利用內(nèi)存,如果使用bool型變量,它是一個字節(jié)大小,其中一個字節(jié)的內(nèi)存中只有一個位被利用,其余的位都被浪費(fèi)了。但是現(xiàn)在內(nèi)存是充裕的,程序員發(fā)現(xiàn)往往將代碼表達(dá)的更加讓人理解,更加容易維護(hù)是一種更好的選擇。
因此,位操作符的使用不再像最初那么平常了,除了一些特殊的環(huán)境中,如需要巨型數(shù)據(jù)處理的科學(xué)計算,或需要超速執(zhí)行的游戲中,仍然會被使用。不管怎么樣,對它有個充分的認(rèn)識和理解還是必須的。
| Operator | Symbol | Form | Operation |
| left shift | << | x << y | all bits in x shifted left y bits |
| right shift | >> | x >> y | all bits in x shifted right y bits |
| bitwise NOT | ~ | ~x | all bits in x flipped |
| bitwise AND | & | x & y | each bit in x AND each bit in y |
| bitwise OR | | | x | y | each bit in x OR each bit in y |
| bitwise XOR | ^ | x ^ y | each bit in x XOR each bit in y |
注意 當(dāng)我們使用位操作符時,使用的變量類型通常是無符號整型。
為操作符的原理通常很簡單,但是要將它用活,通常是有一定難度的。