數(shù)組
前面說了在C++中是通過變量來對內(nèi)存進(jìn)行訪問的,但根據(jù)前面的說明,C++中只能通過變量來操作內(nèi)存,也就是說要操作某塊內(nèi)存,就必須先將這塊內(nèi)存的首地址和一個(gè)變量名綁定起來,這是很糟糕的。比如有100塊內(nèi)存用以記錄100個(gè)工人的工資,現(xiàn)在要將每個(gè)工人的工資增加5%,為了知道各個(gè)工人增加了后的工資為多少,就定義一個(gè)變量float a1;,用其記錄第1個(gè)工人的工資,然后執(zhí)行語句a1 += a1 * 0.05f;,則a1里就是增加后的工資。由于是100個(gè)工人,所以就必須有100個(gè)變量,分別記錄100個(gè)工資。因此上面的賦值語句就需要有100條,每條僅僅變量名不一樣。
上面需要手工重復(fù)書寫變量定義語句float a1;100遍(每次變一個(gè)變量名),無謂的工作。因此想到一次向操作系統(tǒng)申請100*4=400個(gè)字節(jié)的連續(xù)內(nèi)存,那么要給第i個(gè)工人修改工資,只需從首地址開始加上4*i個(gè)字節(jié)就行了(因?yàn)閒loat占用4個(gè)字節(jié))。
為了提供這個(gè)功能,C++提出了一種類型——數(shù)組。數(shù)組即一組數(shù)字,其中的各個(gè)數(shù)字稱作相應(yīng)數(shù)組的元素,各元素的大小一定相等(因?yàn)閿?shù)組中的元素是靠固定的偏移來標(biāo)識的),即數(shù)組表示一組相同類型的數(shù)字,其在內(nèi)存中一定是連續(xù)存放的。在定義變量時(shí),要表示某個(gè)變量是數(shù)組類型時(shí),在變量名的后面加上方括號,在方括號中指明欲申請的數(shù)組元素個(gè)數(shù),以分號結(jié)束。因此上面的記錄100個(gè)工資的變量,即可如下定義成數(shù)組類型的變量:
float a[100];
上面定義了一個(gè)變量a,分配了100*4=400個(gè)字節(jié)的連續(xù)內(nèi)存(因?yàn)橐粋€(gè)float元素占用4個(gè)字節(jié)),然后將其首地址和變量名a相綁定。而變量a的類型就被稱作具有100個(gè)float類型元素的數(shù)組。即將如下解釋變量a所對應(yīng)內(nèi)存中的內(nèi)容(類型就是如何解釋內(nèi)存的內(nèi)容):a所對應(yīng)的地址標(biāo)識的內(nèi)存是一塊連續(xù)內(nèi)存的首地址,這塊連續(xù)內(nèi)存的大小剛好能容納下100個(gè)float類型的數(shù)字。
因此可以將前面的float b;這種定義看成是定義了一個(gè)元素的float數(shù)組變量b。而為了能夠訪問數(shù)組中的某個(gè)元素,在變量名后接方括號,方括號中放一數(shù)字,數(shù)字必須是非浮點(diǎn)數(shù),即使用二進(jìn)制原碼或補(bǔ)碼進(jìn)行表示的數(shù)字。如a[ 5 + 3 ] += 32;就是數(shù)組變量a的第5 + 3個(gè)元素的值增加32。又:
long c = 23; float b = a[ ( c – 3 ) / 5 ] + 10, d = a[ c – 23 ];
上面的b的值就為數(shù)組變量a的第4個(gè)元素的值加10,而d的值就為數(shù)組變量a的第0個(gè)元素的值。即C++的數(shù)組中的元素是以0為基本序號來記數(shù)的,即a[0]實(shí)際代表的是數(shù)組變量a中的第一個(gè)元素的值,而之所以是0,表示a所對應(yīng)的地址加上0*4后得到的地址就為第一個(gè)元素的地址。
應(yīng)該注意不能這樣寫:long a[0];,定義0個(gè)元素的數(shù)組是無意義的,編譯器將報(bào)錯(cuò),不過在結(jié)構(gòu)或類或聯(lián)合中符合某些規(guī)則后可以這樣寫,那是C語言時(shí)代提出的一種實(shí)現(xiàn)結(jié)構(gòu)類型的長度可變的技術(shù),在《C++從零開始(九)》中將說明。
還應(yīng)注意上面在定義數(shù)組時(shí)不能在方括號內(nèi)寫變量,即long b = 10; float a[ b ];是錯(cuò)誤的,因?yàn)榫幾g此代碼時(shí),無法知道變量b的值為多少,進(jìn)而無法分配內(nèi)存。可是前面明明已經(jīng)寫了b = 10;,為什么還說不知道b的值?那是因?yàn)闊o法知道b所對應(yīng)的地址是多少。因?yàn)榫幾g器編譯時(shí)只是將b和一個(gè)偏移進(jìn)行了綁定,并不是真正的地址,即b所對應(yīng)的可能是Base - 54,而其中的Base就是在程序一開始執(zhí)行時(shí)動態(tài)向操作系統(tǒng)申請的大塊內(nèi)存的尾地址,因?yàn)槠淇赡茏兓薀o法得知b實(shí)際對應(yīng)的地址(實(shí)際在Windows平臺下,由于虛擬地址空間的運(yùn)用,是可以得到實(shí)際對應(yīng)的虛擬地址,但依舊不是實(shí)際地址,故無法編譯時(shí)期知道某變量的值)。
但是編譯器仍然可以根據(jù)前面的long b = 10;而推出Base - 54的值為10啊?重點(diǎn)就是編譯器看到long b = 10;時(shí),只是知道要生成一條指令,此指令將10放入Base - 54的內(nèi)存中,其它將不再過問(也沒必要過問),故即使才寫了long b = 10;編譯器也無法得知b的值。
上面說數(shù)組是一種類型,其實(shí)并不準(zhǔn)確,實(shí)際應(yīng)為——數(shù)組是一種類型修飾符,其定義了一種類型修飾規(guī)則。關(guān)于類型修飾符,后面將詳述。
前面說了在C++中是通過變量來對內(nèi)存進(jìn)行訪問的,但根據(jù)前面的說明,C++中只能通過變量來操作內(nèi)存,也就是說要操作某塊內(nèi)存,就必須先將這塊內(nèi)存的首地址和一個(gè)變量名綁定起來,這是很糟糕的。比如有100塊內(nèi)存用以記錄100個(gè)工人的工資,現(xiàn)在要將每個(gè)工人的工資增加5%,為了知道各個(gè)工人增加了后的工資為多少,就定義一個(gè)變量float a1;,用其記錄第1個(gè)工人的工資,然后執(zhí)行語句a1 += a1 * 0.05f;,則a1里就是增加后的工資。由于是100個(gè)工人,所以就必須有100個(gè)變量,分別記錄100個(gè)工資。因此上面的賦值語句就需要有100條,每條僅僅變量名不一樣。
上面需要手工重復(fù)書寫變量定義語句float a1;100遍(每次變一個(gè)變量名),無謂的工作。因此想到一次向操作系統(tǒng)申請100*4=400個(gè)字節(jié)的連續(xù)內(nèi)存,那么要給第i個(gè)工人修改工資,只需從首地址開始加上4*i個(gè)字節(jié)就行了(因?yàn)閒loat占用4個(gè)字節(jié))。
為了提供這個(gè)功能,C++提出了一種類型——數(shù)組。數(shù)組即一組數(shù)字,其中的各個(gè)數(shù)字稱作相應(yīng)數(shù)組的元素,各元素的大小一定相等(因?yàn)閿?shù)組中的元素是靠固定的偏移來標(biāo)識的),即數(shù)組表示一組相同類型的數(shù)字,其在內(nèi)存中一定是連續(xù)存放的。在定義變量時(shí),要表示某個(gè)變量是數(shù)組類型時(shí),在變量名的后面加上方括號,在方括號中指明欲申請的數(shù)組元素個(gè)數(shù),以分號結(jié)束。因此上面的記錄100個(gè)工資的變量,即可如下定義成數(shù)組類型的變量:
float a[100];
上面定義了一個(gè)變量a,分配了100*4=400個(gè)字節(jié)的連續(xù)內(nèi)存(因?yàn)橐粋€(gè)float元素占用4個(gè)字節(jié)),然后將其首地址和變量名a相綁定。而變量a的類型就被稱作具有100個(gè)float類型元素的數(shù)組。即將如下解釋變量a所對應(yīng)內(nèi)存中的內(nèi)容(類型就是如何解釋內(nèi)存的內(nèi)容):a所對應(yīng)的地址標(biāo)識的內(nèi)存是一塊連續(xù)內(nèi)存的首地址,這塊連續(xù)內(nèi)存的大小剛好能容納下100個(gè)float類型的數(shù)字。
因此可以將前面的float b;這種定義看成是定義了一個(gè)元素的float數(shù)組變量b。而為了能夠訪問數(shù)組中的某個(gè)元素,在變量名后接方括號,方括號中放一數(shù)字,數(shù)字必須是非浮點(diǎn)數(shù),即使用二進(jìn)制原碼或補(bǔ)碼進(jìn)行表示的數(shù)字。如a[ 5 + 3 ] += 32;就是數(shù)組變量a的第5 + 3個(gè)元素的值增加32。又:
long c = 23; float b = a[ ( c – 3 ) / 5 ] + 10, d = a[ c – 23 ];
上面的b的值就為數(shù)組變量a的第4個(gè)元素的值加10,而d的值就為數(shù)組變量a的第0個(gè)元素的值。即C++的數(shù)組中的元素是以0為基本序號來記數(shù)的,即a[0]實(shí)際代表的是數(shù)組變量a中的第一個(gè)元素的值,而之所以是0,表示a所對應(yīng)的地址加上0*4后得到的地址就為第一個(gè)元素的地址。
應(yīng)該注意不能這樣寫:long a[0];,定義0個(gè)元素的數(shù)組是無意義的,編譯器將報(bào)錯(cuò),不過在結(jié)構(gòu)或類或聯(lián)合中符合某些規(guī)則后可以這樣寫,那是C語言時(shí)代提出的一種實(shí)現(xiàn)結(jié)構(gòu)類型的長度可變的技術(shù),在《C++從零開始(九)》中將說明。
還應(yīng)注意上面在定義數(shù)組時(shí)不能在方括號內(nèi)寫變量,即long b = 10; float a[ b ];是錯(cuò)誤的,因?yàn)榫幾g此代碼時(shí),無法知道變量b的值為多少,進(jìn)而無法分配內(nèi)存。可是前面明明已經(jīng)寫了b = 10;,為什么還說不知道b的值?那是因?yàn)闊o法知道b所對應(yīng)的地址是多少。因?yàn)榫幾g器編譯時(shí)只是將b和一個(gè)偏移進(jìn)行了綁定,并不是真正的地址,即b所對應(yīng)的可能是Base - 54,而其中的Base就是在程序一開始執(zhí)行時(shí)動態(tài)向操作系統(tǒng)申請的大塊內(nèi)存的尾地址,因?yàn)槠淇赡茏兓薀o法得知b實(shí)際對應(yīng)的地址(實(shí)際在Windows平臺下,由于虛擬地址空間的運(yùn)用,是可以得到實(shí)際對應(yīng)的虛擬地址,但依舊不是實(shí)際地址,故無法編譯時(shí)期知道某變量的值)。
但是編譯器仍然可以根據(jù)前面的long b = 10;而推出Base - 54的值為10啊?重點(diǎn)就是編譯器看到long b = 10;時(shí),只是知道要生成一條指令,此指令將10放入Base - 54的內(nèi)存中,其它將不再過問(也沒必要過問),故即使才寫了long b = 10;編譯器也無法得知b的值。
上面說數(shù)組是一種類型,其實(shí)并不準(zhǔn)確,實(shí)際應(yīng)為——數(shù)組是一種類型修飾符,其定義了一種類型修飾規(guī)則。關(guān)于類型修飾符,后面將詳述。