C++ 語言基礎
1. 局部變量和全局變量能否重名?
局部變量是定義在函數(shù)內部的變量游盲。
全局變量是定義在函數(shù)之外的變量介袜,可以被本文件中其他函數(shù)所共用。
局部變量和全局變量可以重名唁影,在函數(shù)中默認使用的是局部變量(即會屏蔽全局變量)耕陷。要使用全局變量,要在變量名前添加 “::” 据沈。
2. 全局變量可不可以被定義在可被多個 .c 文件包含的頭文件中哟沫?為什么?
可以锌介,因為可以在不同的 .c 文件中以 static 形式來聲明同名的全局變量嗜诀,但是在這些同名的全局變量中只能有一個 .c 文件對其進行賦值,這樣才不會出錯孔祸。
3. 如何引用一個已經(jīng)定義過的全局變量隆敢?
- 用引用頭文件的方式
- 用 extern 關鍵字引用
注意:使用頭文件的方式來引用某個頭文件中的全局變量,如果變量名書寫錯誤融击,則在編譯時提示錯誤筑公;使用 extern 關鍵字引用時,如果變量名書寫錯誤尊浪,則在鏈接時提示錯誤匣屡。
4. 全局變量和局部變量在內存中是怎樣存放的?兩者之間有何區(qū)別拇涤?
全局變量存儲在靜態(tài)數(shù)據(jù)庫捣作,局部變量存儲在堆棧。
全局變量在程序開始執(zhí)行時分配存儲區(qū)鹅士,程序執(zhí)行完畢釋放券躁,在程序執(zhí)行過程中全局變量始終占據(jù)固定的存儲單元;局部變量是動態(tài)分配存儲空間的,在函數(shù)調用結束時自動釋放這些存儲空間也拜。
5. -8 在內存中的存儲形式以舒?
整型數(shù)據(jù)在內存中是以二進制的形式存放的,數(shù)值是以補碼表示的慢哈。
一個正數(shù)的補碼和其原碼的形式相同蔓钟,一個負數(shù)的補碼是將該數(shù)二進制形式符號位保持不變,其余按位取反再加 1 卵贱。
所以 -8 在內存中的存儲形式是 11111111 11111000 滥沫。
6. 數(shù)值 029 是一個什么數(shù)?
非法數(shù)键俱。
本題主要是對八進制兰绣、十六進制和十進制三種形式的考察。八進制整常數(shù)必須以 0 開頭编振,數(shù)碼取值為 0 ~ 7缀辩;十六進制整常數(shù)是以 0X 或 0x 開頭的,數(shù)碼取值為 0 ~ 9踪央,A ~ F 或 a ~ f 雌澄;十進制整常數(shù)無前綴,數(shù)碼為 0 ~ 9 杯瞻。
這里的 029 是以 0 開頭镐牺,卻含有 9 ,所以不是八進制數(shù)魁莉,因此它是非法的睬涧。
7. 整數(shù)除法取值
請問 i 和 j 的值分別是什么?
int i, j;
i = 5 / 2;
j = -5 / 2;
i = 2旗唁,j = -2
對于整數(shù)除法取值來說畦浓,在 C/C++ 中是將結果的小數(shù)部分截掉,只保留整數(shù)部分检疫。
8. 寫出 float a 與“零值”比較的 if 語句
if ((a >= -0.00001) && (a <= 0.00001));
本題考察 float 型變量特性及對 0 值的判斷讶请。
一般來說,如果用 if 判斷一個整型變量(short屎媳、int夺溢、long 等),應該用 if (a == 0) 烛谊,表明是與 0 進行“數(shù)值”上的比較风响;但是 float 型變量并不精確,不能直接拿來與 0.0 進行比較丹禀,所以不可使用 “==” 或 “!=” 這種形式状勤,應該使用 “>=” 或 “<=” 這種形式鞋怀。因為計算機在處理浮點數(shù)的時候是有誤差的,所以判斷兩個浮點數(shù)是不是相同持搜,是要判斷是不是落在同一個區(qū)間的密似。
9. 如何將單精度數(shù)值保留小數(shù)點后兩位,第三位四舍五入葫盼?
float a = 1.2345;
//將 (a * 100 + 0.5) 的值強制轉換為整數(shù)值再進行計算
a = (int) (a * 100 + 0.5) / 100.0;
10. 整數(shù)自動轉換原則
下面代碼輸出是什么辛友?為什么?
unsigned int a = 6;
int b = -20;
(a + b > 6) ? puts("> 6") : puts("<= 6");
輸出為 “> 6” 剪返,因為當表達式中存在有符號類型和無符號類型時所有的操作數(shù)會自動轉換為無符號類型。因此 -20 被轉換為 0xffffffec (4294967276) (即取補碼)邓梅,所以該表達式計算出的結果大于 6 脱盲。
在 C/C++ 中無符號類型只能存放不帶符號的整數(shù),不能存放負數(shù)日缨,當為其賦值為負數(shù)時钱反,會自動轉換為無符號類型數(shù)值,其取值范圍是 0 ~ 2 ^ 32 - 1 匣距。
11. 逗號表達式
看下面代碼面哥,輸出結果是什么?
int a, b, c, d;
a = 3;
b = 5;
c = a, b;
d = (a, b);
printf("c = %d\n", c);
printf("d = %d\n", d);
c = 3
d = 5
在 C/C++ 中逗號有兩個作用毅待,一是用來分隔表達式尚卫,二是作為逗號運算符。
C++ 提供一種特殊的運算符——逗號運算符尸红,用它將兩個表達式連接起來吱涉。如:** 3 + 5, 6 + 8 稱為逗號表達式,又稱為“順序求值運算符”外里。逗號表達式的一般形式為:表達式 1 , 表達式 2** 怎爵。
逗號表達式的求解過程是:先求解表達式 1 ,再求解表達式 2 盅蝗。整個逗號表達式的值是表達式 2 的值鳖链。如,逗號表達式 a = 3 * 5 , a * 4 賦值運算符的優(yōu)先級別高于逗號運算符墩莫, 因此應先求解 a = 3 * 5 (也就是把“a = 3 * 5”作為一個表達式)芙委。經(jīng)計算和賦值后得到 a 的值為 15 ,然后求解 a * 4 狂秦,得 60 题山。整個逗號表達式的值為 60 。
12. printf() 函數(shù)和 cout 函數(shù)是從右向左計算輸出表達式的值
13. static 關鍵字
C++ 的 static 有兩種用法:面向過程程序設計中的 static 和面向對象程序設計中的 static 故痊。前者應用于普通變量和函數(shù)顶瞳,不涉及類;后者主要說 static 在類中的作用。
一慨菱、面向過程設計中的 static
1焰络、靜態(tài)全局變量
在全局變量前,加上關鍵字 static符喝,該變量就被定義成為一個靜態(tài)全局變量闪彼。靜態(tài)全局變量有以下特點:
(1)該變量在全局數(shù)據(jù)區(qū)分配內存;
(2)未經(jīng)初始化的靜態(tài)全局變量會被程序自動初始化為 0(自動變量的值是隨機的协饲,除非它被顯式初始化)畏腕;
(3)靜態(tài)全局變量在聲明它的整個文件都是可見的,而在文件之外是不可見的茉稠。(利用這一特性可以在不同的文件中定義同名函數(shù)和同名變量描馅,而不必擔心命名沖突。)
2而线、靜態(tài)局部變量
在局部變量前铭污,加上關鍵字 static ,該變量就被定義成為一個靜態(tài)局部變量膀篮。靜態(tài)局部變量有以下特點:
(1)該變量在全局數(shù)據(jù)區(qū)分配內存嘹狞;
(2)靜態(tài)局部變量在程序執(zhí)行到該對象的聲明處時被首次初始化,即以后的函數(shù)調用不再進行初始化誓竿;
(3)靜態(tài)局部變量一般在聲明處初始化磅网,如果沒有顯式初始化,會被程序自動初始化為 0 筷屡;
(4)它始終駐留在全局數(shù)據(jù)區(qū)知市,直到程序運行結束。但其作用域為局部作用域速蕊,當定義它的函數(shù)或語句塊結束時嫂丙,其作用域隨之結束;
3规哲、靜態(tài)函數(shù)
在函數(shù)的返回類型前加上 static 關鍵字,函數(shù)即被定義為靜態(tài)函數(shù)跟啤。靜態(tài)函數(shù)與普通函數(shù)不同,它只能在聲明它的文件當中可見唉锌,不能被其它文件使用隅肥。定義靜態(tài)函數(shù)的好處:
(1)靜態(tài)函數(shù)不能被其它文件所用;
(2)其它文件中可以定義相同名字的函數(shù)袄简,不會發(fā)生沖突腥放;
二、面向對象的 static 關鍵字(類中的 static 關鍵字)
1绿语、靜態(tài)數(shù)據(jù)成員
在類內數(shù)據(jù)成員的聲明前加上關鍵字 static 秃症,該數(shù)據(jù)成員就是類內的靜態(tài)數(shù)據(jù)成員候址。靜態(tài)數(shù)據(jù)成員有以下特點:
(1)對于非靜態(tài)數(shù)據(jù)成員,每個類對象都有自己的拷貝种柑。而靜態(tài)數(shù)據(jù)成員被當作是類的成員岗仑。無論這個類的對象被定義了多少個,靜態(tài)數(shù)據(jù)成員在程序中也只有一份拷貝聚请,由該類型的所有對象共享訪問荠雕。也就是說,靜態(tài)數(shù)據(jù)成員是該類的所有對象所共有的驶赏。對該類的多個對象來說炸卑,靜態(tài)數(shù)據(jù)成員只分配一次內存,供所有對象共用煤傍。所以盖文,靜態(tài)數(shù)據(jù)成員的值對每個對象都是一樣的,它的值可以更新患久;
(2)靜態(tài)數(shù)據(jù)成員存儲在全局數(shù)據(jù)區(qū)。靜態(tài)數(shù)據(jù)成員定義時要分配空間浑槽,所以不能在類聲明中定義蒋失。
(3)靜態(tài)數(shù)據(jù)成員和普通數(shù)據(jù)成員一樣遵從 public , protected 桐玻, private 訪問規(guī)則篙挽;
(4)因為靜態(tài)數(shù)據(jù)成員在全局數(shù)據(jù)區(qū)分配內存,屬于本類的所有對象共享镊靴,所以铣卡,它不屬于特定的類對象,在沒有產生類對象時其作用域就可見偏竟,即在沒有產生類的實例時煮落,我們就可以操作它;
(5)靜態(tài)數(shù)據(jù)成員初始化與一般數(shù)據(jù)成員初始化不同踊谋。靜態(tài)數(shù)據(jù)成員初始化的格式為:
<數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員名>=<值>
(6)類的靜態(tài)數(shù)據(jù)成員有兩種訪問形式:
<類對象名>.<靜態(tài)數(shù)據(jù)成員名> 或 <類類型名>::<靜態(tài)數(shù)據(jù)成員名>
如果靜態(tài)數(shù)據(jù)成員的訪問權限允許的話(即 public 的成員)蝉仇,可在程序中,按上述格式來引用靜態(tài)數(shù)據(jù)成員 殖蚕;
(7)靜態(tài)數(shù)據(jù)成員主要用在各個對象都有相同的某項屬性的時候轿衔。比如對于一個存款類,每個實例的利息都是相同的睦疫。所以害驹,應該把利息設為存款類的靜態(tài)數(shù)據(jù)成員。這有兩個好處蛤育,第一宛官,不管定義多少個存款類對象葫松,利息數(shù)據(jù)成員都共享分配在全局數(shù)據(jù)區(qū)的內存,所以節(jié)省存儲空間摘刑。第二进宝,一旦利息需要改變時,只要改變一次枷恕,則所有存款類對象的利息全改變過來了党晋;
(8)同全局變量相比,使用靜態(tài)數(shù)據(jù)成員有兩個優(yōu)勢:靜態(tài)數(shù)據(jù)成員沒有進入程序的全局名字空間徐块,因此不存在與程序中其它全局名字沖突的可能性未玻;可以實現(xiàn)信息隱藏,靜態(tài)數(shù)據(jù)成員可以是 private 成員胡控,而全局變量不能扳剿。
2、靜態(tài)成員函數(shù)
與靜態(tài)數(shù)據(jù)成員一樣昼激,我們也可以創(chuàng)建一個靜態(tài)成員函數(shù)庇绽,它為類的全部對象服務而不是為類的某一個具體對象服務。靜態(tài)成員函數(shù)有以下特點:
(1)普通的成員函數(shù)一般都隱含了一個 this 指針橙困, this 指針指向類的對象本身瞧掺,因為普通成員函數(shù)總是具體的屬于某個類的具體對象的。通常情況下凡傅, this 是缺省的辟狈。但是與普通函數(shù)相比,靜態(tài)成員函數(shù)由于不是與任何的對象相聯(lián)系夏跷,因此它不具有 this 指針哼转。從這個意義上講,它無法訪問屬于類對象的非靜態(tài)數(shù)據(jù)成員槽华,也無法訪問非靜態(tài)成員函數(shù)壹蔓,它只能調用其余的靜態(tài)成員函數(shù)。
(2)出現(xiàn)在類體外的函數(shù)定義不能出現(xiàn)關鍵字 static 猫态;
(3)靜態(tài)成員之間可以相互訪問庶溶,包括靜態(tài)成員函數(shù)訪問靜態(tài)數(shù)據(jù)成員和訪問靜態(tài)成員函數(shù);
(4)非靜態(tài)成員函數(shù)可以任意地訪問靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員懂鸵;
(5)由于沒有this指針的額外開銷偏螺,因此靜態(tài)成員函數(shù)與類的全局函數(shù)相比速度上會有少許的增長;
(6)調用靜態(tài)成員函數(shù)匆光,可以用成員訪問操作符( . )和( -> )為一個類的對象或指向類對象的指針調用靜態(tài)成員函數(shù)套像,也可以直接使用如下格式:
<類名>::<靜態(tài)成員函數(shù)名>(<參數(shù)表>)
調用類的靜態(tài)成員函數(shù)。
14. const 關鍵字
const 意味著“只讀”终息。const 在誰后面誰就不可修改夺巩,const 在最前面則將其后移一位即可贞让,二者等效。主要優(yōu)點是便于類型檢查柳譬、同宏定義一樣可以方便地進行參數(shù)修改和調整喳张、節(jié)省空間、避免不必要的內存分配美澳、可為函數(shù)重載提供參考销部。
const int a; //a 是一個常整型數(shù)
int const a; //a 是一個常整型數(shù)
const int *a; //a 是一個指向常整型數(shù)的指針,指向的整型數(shù)是不可修改的制跟,但指針可以
int * const a; //a 是一個指向整型數(shù)的常指針舅桩,指針指向的整型數(shù)是可以修改的,但指針是不可修改的
int const * a const; //a 是一個指向常整型數(shù)的常指針雨膨,指針指向的整型數(shù)是不可修改的擂涛,同時指針也是不可修改的
const 的作用如下:
(1)欲阻止一個變量被改變,可以使用 const 關鍵字聊记。在定義該 const 變量時撒妈,通常需要對它進行初始化,因為以后就沒有機會再去改變它了排监;
(2)對指針來說狰右,可以指定指針本身為const,也可以指定指針所指的數(shù)據(jù)為const社露,或二者同時指定為const挟阻;
(3)在一個函數(shù)聲明中琼娘,const可以修飾形參峭弟,表明它是一個輸入?yún)?shù),在函數(shù)內部不能改變其值脱拼;
(4)對于類的成員函數(shù)瞒瘸,若指定其為const類型,則表明其是一個常函數(shù)熄浓,不能修改類的成員變量情臭;
(5)對于類的成員函數(shù),有時候必須指定其返回值為const類型赌蔑,以使得其返回值不為“左值”俯在。
參考:
關鍵字const有什么含義?
c語言中const關鍵字詳解
15. 請說出 const 與 #define 相比有何優(yōu)點娃惯?
(1)const 修飾的只讀變量具有特定的類型跷乐,而宏沒有數(shù)據(jù)類型。編譯
器可以對前者進行類型安全檢查趾浅,而對后者只進行字符替換愕提,沒有類型安全檢查馒稍,并且在字符替換可能會產生意料不到的錯誤。
(2)有些集成化的調試工具可以對 const 常量進行調試浅侨,但是不能對宏
常量進行調試纽谒。
(3)編譯器通常不為普通 const 只讀變量分配存儲空間,而是將它們保
存在符號表中如输,這使得它成為一個編譯期間的值鼓黔,沒有了存儲與讀內存的操作,使得它的效率也很高挨决。
參考:
關鍵字const(1)
16. sizeof 關鍵字
sizeof 實際上是關鍵字请祖,使用類似于一元操作符,所以有時也會被當作一元操作符脖祈。它的作用是返回一個對象或類型名的長度肆捕,長度的單位是字節(jié),它是在編譯階段求值的盖高。sizeof 運算符永遠不會產生 0慎陵,即使對于空類也是如此。
sizeof 有三種語法形式喻奥,如下:
- sizeof( object ); // sizeof( 對象 );
- sizeof( type_name ); // sizeof( 類型 );
- sizeof object; // sizeof 對象;
結論:不論sizeof要對誰取值席纽,最好都加上()。
實際上撞蚕, sizeof 計算對象的大小也是轉換成對對象類型的計算润梯,也就是說,同種類型的不同對象其 sizeof 值都是一致的甥厦。這里纺铭,對象可以進一步延伸至表達式,即 sizeof 可以對一個表達式求值刀疙,編譯器根據(jù)表達式的最終結果類型來確定大小舶赔,一般不會對表達式進行計算。
各種對象或類型名的大星怼:(在 32 位系統(tǒng)中)
1. 基本數(shù)據(jù)類型
bool:1竟纳, char:1, short:2疚鲤, float:4锥累, int:4, long:4集歇, double:8桶略。
2. 指針
不管是什么類型的指針,大小都是 4 個字節(jié)的,因為指針就是 32 位的物理地址删性。
3. 數(shù)組
數(shù)組的大小是各維數(shù)的乘積 * 數(shù)組元素的大小亏娜。
這里有一個陷阱:
int *d = new int[10];
cout << sizeof(d) << endl; // 4
d 是我們常說的動態(tài)數(shù)組,但它實際上還是一個指針蹬挺,所以 sizeof(d) = 4维贺。
4. 函數(shù)
對函數(shù)使用 sizeof ,在編譯階段會被函數(shù)返回值的類型取代巴帮。
5. 自定義數(shù)據(jù)類型
自定義類型的 sizeof 取值等同于它的類型原形溯泣。
6. 聯(lián)合體
union 的大小取決于它所有的成員中,占用空間最大的一個成員的大小榕茧。
復合數(shù)據(jù)類型垃沦,如 union , struct 用押, class 的對齊方式為成員中對齊方式最大的成員的對齊方式肢簿。
6. 結構體
為了性能考慮,編譯器會對結構體進行對齊蜻拨。
struct
{
int b;//4
double a;//8
char c;//1
}A;
sizeof(A) = 24 池充,內存布局如下:
|<<<b=4>>>|補齊4個字節(jié)|<<<<<<<a=8>>>>>>>>|<c=1>|<<補齊7個字節(jié)>>|
struct
{
double a;
int b;
char c;
}A;
sizeof(A) = 16,內存布局如下:
|<<<<<<<<<<<a=8>>>>>>>>>>|<<<<b=4>>>>|<c=1>|<<補齊3個字節(jié)>>|
7. 類
空類大卸兴稀:1收夸。
(1)類的大小為類的非靜態(tài)成員數(shù)據(jù)的類型大小與虛指針(如果有的話)之和,也就是說靜態(tài)成員數(shù)據(jù)和普通成員函數(shù)不作考慮血崭。
(2)類的總大小也遵守類似結構體字節(jié)對齊的調整規(guī)則卧惜。
幾種簡單情況需要記住:空類為 1 夹纫,單一繼承的空類空間也為 1 咽瓷,多重繼承的空類空間還是為 1 。但是虛繼承的空類設計到虛表(虛指針)捷凄,所以為 4 忱详。
17. sizeof 和 strlen 的區(qū)別围来?
- sizeof 是一個操作符跺涤,而 strlen 是庫函數(shù)。
- sizeof 的參數(shù)可以是數(shù)據(jù)的類型监透,也可以是變量桶错,而 strlen 只能以結尾為 '\0' 的字符串作參數(shù)。
- 編譯器在編譯時就計算出了 sizeof 的結果胀蛮,而 strlen 必須在運行時才能計算出來院刁。
- sizeo f計算數(shù)據(jù)類型占內存的大小, strlen 計算字符串實際長度粪狼。