真題
C++
- 函數指針和指針函數的區別? o(╥﹏╥)o
- 堆和棧的區別
- 函數重載?為什么返回值不可以區分函數重載?o(╥﹏╥)o
- 封裝、繼承和多態的定義,自己描述一下這三者的區別和聯系。
- 多態的構成(應該是想聽虛函數,當時沒有想到? o(╥﹏╥)o)
- 必須存在繼承關系
- 繼承關系中必須存在同名的虛函數,并且子類和基類虛函數之間是遮蔽(覆蓋)的關系
- 存在基類指針,通過這個指針實現虛函數的調用
- 進程相較于線程 還多包含一個socket通信o(╥﹏╥)o
- STL
密碼學
- RSA padding模式是啥? 大
- RSA的位數 1024 2048 4096
- 密碼體制? 密碼的底層原理
- 橢圓雙曲線
- 對稱算法的模式? ofb? cfb
- 服務器密碼機如何對外提供服務?帶寬
區塊鏈
- 數字錢包的標準
- 檢測賬戶余額的方法 UTXO
?準備階段
C++
1,fork的底層實現是什么?
fork()函數的底層實現原理_everthing willl be ok-CSDN博客_fork原理
- fork()系統調用通過復制一個現有進程來創建一個全新的進程。進程被存放在一個叫做任務隊列的雙向循環鏈表當中,鏈表當中的每一項都是類型為task_struct稱為進程描述符的結構,也就是我們寫過的進程PCB.?
- Tips:內核通過一個位置的進程標識值或PID來標識每一個進程。//最大值默認為32768,short int短整型的最大值.,他就是系統中允許同時存在的進程最大的數目。
- 可以到目錄 /proc/sys/kernel中查看pid_max:
當進程調用fork后,當控制轉移到內核中的fork代碼后,內核會做4件事情:
- 1、分配新的內存塊和內核數據結構給子進程
- 2、將父進程部分數據結構內容拷貝至子進程
- 3、添加子進程到系統進程列表當中
- 4、fork返回,開始調度器調度
?fork函數在底層到底做了什么呢?
-
Linux平臺通過clone()系統調用實現fork()。 fork(),vfork()和clone()庫函數都根據各自需要的參數標志去調用clone(),然后由clone()去調用do_fork(), 再然后do_fork()完成了創建中的大部分工作,該函數調用copy_process().做最后的那部分工作。
2,智能指針原理、使用和實現
理解智能指針
C++11中智能指針的原理、使用、實現 - wxquare - 博客園
- 智能指針是利用了一種叫做RAII(資源獲取即初始化)的技術對普通的指針進行封裝,這使得智能指針實質是一個對象,行為表現的卻像一個指針
- 智能指針的作用是防止忘記調用delete釋放內存和程序異常的進入catch塊忘記釋放內存。另外指針的釋放時機也是非常有考究的,多次釋放同一個指針會造成程序崩潰,這些都可以通過智能指針來解決
智能指針占據的字節數
- shared_ptr? 16字節
- unique_ptr? 8字節
- weak_ptr? 16字節
3,虛函數
C++虛函數詳解_C語言中文網
C++ 虛函數表解析_陳皓專欄 【空谷幽蘭,心如皓月】-CSDN博客_虛函數表
C++虛函數詳解_Whitesad的博客-CSDN博客_c++虛函數
- 只有派生類的虛函數遮蔽基類的虛函數(函數原型相同)才能構成多態(通過基類指針訪問派生類函數)
- 虛函數的聲明的前提:首先看成員函數所在的類是否會作為基類。然后看成員函數在類的繼承后有無可能被更改功能,如果希望更改其功能的,一般應該將它聲明為虛函數。如果成員函數在類被繼承后功能不需修改,或派生類用不到該函數,則不要把它聲明為虛函數
- 虛函數是運行時決議,與一般的編譯時決議存在很大的不同
- 虛函數指針:虛函數指針式一個指向函數的指針,指向的是子類內部實現的虛函數,當子類調用虛函數的時候,本質上是通過調用這個虛函數指針找到接口
- 虛函數指針是確實存在的數據類型,在一個被實例化的對象中,它總是被存放在該對象的地址首位,這種做法的目的是為了保證運行的快速性。與對象的成員不同,虛函數指針對外部是完全不可見的,除非通過直接訪問地址的做法或者在DEBUG模式中,否則它是不可見的也不能被外界調用
4,C++轉型操作符? 強制類型轉換
- const_cast?通常用來將對象的常量性轉除(cast away the constness)。它是唯一有此能力的C++-style轉型操作符
- dynamic_cast用來執行繼承體系中安全的向下轉型或跨系轉型動作。也就是說你可以利用它將指向基類對象的指針或者引用轉型為指向派生類對象的指針或引用,并得知轉型是否成功。如果轉型失敗,會以一個null指針(當轉型對象是指針)或一個exception(當轉型對象是引用)表現出來。dynamic_cast是唯一無法由舊式語法執行的轉型動作,也是唯一可能消耗重大運行成本的轉型動作
- static_cast?基本上擁有與C舊式轉型相同的威力與意義,以及相同的限制。例如將一個非?const?的對象轉換為?const?對象,或將int?轉換為?double等等。它也可以用來執行上述多種轉換的反向轉換,例如將void*指針轉為typed指針,將pointer-to-base轉為pointer-to-derived。但是他無法將const轉為non-const,這個只有const-cast才能夠辦到
- reinterpret_cast意圖執行低級轉型,實際動作及結果可能取決于編譯器,這也就表示它不可移植。例如將一個pointer to int?轉型為int。這一類轉型在低級代碼以外很少見
5,new和malloc的區別
c++ new 與malloc有什么區別 - ywliao - 博客園
- new操作符從自由存儲區(free store)上為對象動態分配內存空間,而malloc函數從堆上動態分配內存。自由存儲區是否能夠是堆(問題等價于new是否能在堆上動態分配內存),這取決于operator new 的實現細節。自由存儲區不僅可以是堆,還可以是靜態存儲區,這都看operator new在哪里為對象分配內存。
- new操作符內存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無須進行類型轉換,故new是符合類型安全性的操作符。而malloc內存分配成功則是返回void * ,需要通過強制類型轉換將void*指針轉換成我們需要的類型。
- new內存分配失敗時,會拋出bac_alloc異常,它不會返回NULL;malloc分配內存失敗時返回NULL。
- 使用new操作符申請內存分配時無須指定內存塊的大小,編譯器會根據類型信息自行計算,而malloc則需要顯式地指出所需內存的尺寸。
?5,C++仿照標準字符串類string,設計一個自己的字符串類String
C++仿照標準字符串類string,設計一個自己的字符串類String_之古的博客-CSDN博客_設計一個字符串類string
?主要的任務
- 1)數據成員是字符指針,可自動適應不同的串長度。
- 2)串復制,既可使用字符串常量進行復制,也可以使用其他的字符串對象進行復制。
- 3)串賦值。既可賦值為字符串常量,也可以賦值為使用其他的字符串對象。
- 4)串連接。重載“+”和“+=”。
- 5)重載下標運算符[]。
- 6)串比較。重載“==”和“<”。
- 7)字符串輸入和輸出。重載“>>”和“<<”。
#include<iostream>
#include<cstring>
using namespace std;
class String {
private:char * Pstr;
public:String(const char* p = NULL) {if (p == NULL) {Pstr = new char[1];*Pstr = '\0';} else {Pstr = new char[strlen(p) + 1];strcpy(Pstr, p);}}String(const String& s): Pstr(new char[strlen(s.Pstr) + 1]) {strcpy(Pstr, s.Pstr);}~String() {if (Pstr)delete[] Pstr;}String& operator=(const String& s) {if (Pstr == s.Pstr)return *this;else if (NULL == this) {delete Pstr;Pstr = new char[strlen(s.Pstr) + 1];strcpy(Pstr, s.Pstr);} else {strcpy(Pstr, s.Pstr);}return *this;}friend ostream & operator<<(ostream &out, const String &s) {out << s.Pstr;return out;}friend istream & operator >>(istream &in, String &s) {in >> s.Pstr;if(in)return in;}String operator+(const String &s2) {char *p=new char[strlen(Pstr) + strlen(s2.Pstr)+1];p=strcat(Pstr,s2.Pstr);return String(p);}void operator+=(const String &s2) {strcat(Pstr, s2.Pstr);}char& operator[](int n) {return Pstr[n];}int Length() {int n=strlen(Pstr) ;return n;}bool operator==(const String &s2) {return strcmp(Pstr, s2.Pstr) == 0;}bool operator<(const String &s2) {return strcmp(Pstr, s2.Pstr) < 0;}
};
6,文件編譯的過程
C 文件編譯的過程_sxy19930313的博客-CSDN博客
gcc編譯程序的四個階段(預處理-編譯-匯編-鏈接)_Aikenlan的博客-CSDN博客
預編譯 :
- 處理所有的注釋 , 以空格代替
- 將所有的 #define刪除 ,并且展開所有的宏定義
- 處理條件編譯指令#if、#ifdef、#elf、#else、#endif
- 處理#include,展開被包含的文件
- 保留編譯器需要使用的#pragma指令
- 預處理指令:gcc ?? -E? file.c? -o? hello.i ????
編譯
- 對預處理的文件進行一系列詞法分析、語法分析和語義分析
- 詞法分析主要分析關鍵字,標識符,立即數等是否合法? ? ? ? ? ? ?
- 語法分析主要分析表達式是否遵循語法規則? ? ? ? ? ? ? ? ?
- 語義分析是在語法分析的基礎上進一步分析表達式是否合法 ? ? ? ?
- 分析結束后進行代碼優化生成相應的匯編代碼文件 ? ? ? ? ? ?
- 編譯指令: ?gcc ? -S ?file.c ?-o hello.s
匯編
- 匯編器將匯編代碼轉變為機器可以執行的指令 ?
- 匯編階段生成 二進制代碼
- 每個匯編語句幾乎都對應一條機器指令 匯編指令:gcc ?-c file.s ?-o ?hello.o? ? ? ? ? ? ?
鏈接
- ? ?鏈接器的主要作用是把各個模塊之間相互引用的部分處理好,使得各個模塊之間能夠正確的銜接
- 靜態鏈接:在編譯期間完成,鏈接文件是以目標文件為單位的,如果有多個可執行文件調用同一個函數,則該函數的目標文件就會生成多個副本,并與多個可執行文件一一對應。這樣就造成來了內存空間得了浪費,同時函數庫的更新也很麻煩。優點是程序在運行的時候已經包含了所有的程序,運行速度較快
- ?動態鏈接:在運行期間完成
?7,并行和并發的區別
面試必考的:并發和并行有什么區別? - 云+社區 - 騰訊云
- 并發一段時間內? 實現兩個程序的執行? 不可以同時
- 并行是同一時刻? 實現兩個程序的執行? 可以同時
?8,中斷
為什么需要中斷?_jwy2014的專欄-CSDN博客_為什么要使用中斷
什么是中斷,為什么要用中斷?_old-li的blog-CSDN博客
9,邏輯地址 和 物理地址的區別
物理地址、虛擬地址和邏輯地址之間的區別_SoaringLee_fighting的技術專欄-CSDN博客
- 物理地址就是,機器內主存的地址,包括RAM和ROM
- 邏輯地址就是,程序運行在內存中,使用的地址。
- 虛擬地址就是,cpu支持的內存空間遠遠大于機器主存的大小,這些多出來的空間對于程序來說是可以用的,這個時候的所有地址都稱為虛擬地址
補充
C++ Primer:常量引用、引用常量、常量指針、指針常量 - 簡書
- 函數指針? 指針函數
- 常量指針? 指針常量
- 數組指針? 指針數組
- 常量引用? 引用常量
函數指針 和? 指針函數的區別
C++ 函數指針和指針函數-CJavaPy
指針函數
- 指針函數本質是返回指針的函數,其本質是一個函數,返回的類型是指針。int *myfun(int x,int y);??在函數名前面多了一個*號,而這個函數就是一個指針函數。其返回值是一個 int 類型的指針。
#include <iostream>
using namespace std;
#include<string.h>int *newAdd(int a, int b); // 聲明指針函數int main() {int *p1 = NULL;p1 = newAdd(1, 2);printf("p1 = 0x%x \n", p1);printf("*p1 = %d \n", *p1);getchar();return 0;
}
int *newAdd(int a, int b) {int *p = (int *)malloc(sizeof(int));memset(p, 0, sizeof(int));printf("函數內:p = 0x%x \n", p);*p = a + b;printf("函數內:*p = %d \n", *p);return p;
}
- 在調用指針函數時,需要一個同類型的指針來接收其函數的返回值。 也可以將其返回值定義為 void*類型,調用時強制轉換返回值為想要的類型。
函數指針
- 函數指針,其本質是一個指針變量,該指針指向這個函數。函數指針就是指向函數的指針。聲明格式如下:int (*myfun)(int x,int y);
#include <iostream>
using namespace std;
int add(int x,int y){return x+y;
}
int sub(int x,int y){return x-y;
}
//函數指針
int (*myfun)(int x,int y);
int main(int argc, char *argv[])
{//第一種寫法myfun = add;cout << "(*myfun)(1,2) = " << (*myfun)(1,2) << endl;//第二種寫法myfun = ⊂cout << "(*myfun)(5,3) = " << myfun(5,3) << endl;return 0;
}
區別
1)定義不同
- 指針函數本質是一個函數,其返回值為指針。
- 函數指針本質是一個指針,其指向一個函數。
2)寫法不同
- 指針函數:
int* fun(int x,int y);
- 函數指針:
int (*fun)(int x,int y);
- 函數名帶括號的就是函數指針,否則就是指針函數。
3)用法不同
- 一個是函數,一個是變量
對特定地址進行賦值
如何給地址賦值?(轉) - 張凌001 - 博客園
C語言中給指定的內存地址賦值(通過指針)_phenixyf的專欄-CSDN博客
- 對于i分配的地址具有訪問權限?
int i = 0;std::cout << &i << std::endl;int *ptr = (int *)(&i);*ptr = 55;std::cout << *(int *)(&i)<<std::endl;
?全局變量和靜態全局變量 區別
全局變量和靜態全局變量_calm_peng-CSDN博客_靜態全局變量
靜態函數和普通函數的區別
static函數與普通函數的區別:用static修飾的函數,本限定在本源碼文件中,不能被本源碼文件以外的代碼文件調用。而普通的函數,默認是extern的,也就是說,可以被其它代碼文件調用該函數。在函數的返回類型前加上關鍵字static,函數就被定義成為靜態函數。普通 函數的定義和聲明默認情況下是extern的,但靜態函數只是在聲明他的文件當中可見,不能被其他文件所用。因此定義靜態函數有以下好處:<1> 其他文件中可以定義相同名字的函數,不會發生沖突。<2> 靜態函數不能被其他文件所用。
計算機網絡
OSI七層網絡模型,以及每層對于的網絡協議
OSI七層模型及對應的網絡協議_小麻花-CSDN博客_七層模型對應的協議
https的底層實現,原理是什么?
HTTPS底層實現原理_風某人~Wind的博客-CSDN博客_https的底層原理
- 證書(CRT文件,里面包含了公鑰,CA的簽名,過期時間,申請人提交的信息)
- https = http+SSL 12次
TCP? UDP 區別
一文搞懂TCP與UDP的區別 - Fundebug - 博客園
UDP | TCP | |
是否連接 | 無連接 | 面向連接 |
是否可靠 | 不可靠傳輸,不使用流量控制和擁塞控制 | 可靠傳輸,使用流量控制和擁塞控制 |
連接對象個數 | 支持一對一,一對多,多對一和多對多交互通信 | 只能是一對一通信 |
傳輸方式 | 面向報文 | 面向字節流 |
首部開銷 | 首部開銷小,僅8字節 | 首部最小20字節,最大60字節 |
適用場景 | 適用于實時應用(IP電話、視頻會議、直播等) | 適用于要求可靠傳輸的應用,例如文件傳輸 |
?
Linux
Linux 驅動模型?
Linux驅動學習:應先了解驅動模型 - 知乎
[Linux]互斥機制(中斷屏蔽、原子操作、自旋鎖、信號量)
[Linux]互斥機制(中斷屏蔽、原子操作、自旋鎖、信號量)_Younix凌亂的草稿本-CSDN博客
Linux進程之間通信方式
進程間8種通信方式詳解 - 云+社區 - 騰訊云
進程間通信的方式——信號、管道、消息隊列、共享內存 - 0giant - 博客園
用戶態和內核態的區分
用戶態和內核態的區別 - Gizing - 博客園
查看linux的位數 不能使用sizeof
查看當前linux系統位數 - controlV - 博客園
- uname -a
- uname -r
命令1:getconf LONG_BIT
結果:64命令2:uname -a
結果:Linux Test004MUJUP 2.6.32-431.23.3.el6.x86_64 #1 SMP Wed Jul 16 06:12:23 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux命令3:uname -r
結果:2.6.32-431.23.3.el6.x86_64命令4:cat /proc/version
結果:Linux version 2.6.32-431.23.3.el6.x86_64 (mockbuild@x86-027.build.eng.bos.redhat.com) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Wed Jul 16 06:12:23 EDT 2014
參考資料
- C++進階問題-智能指針&繼承&sizeof - 杭河葦 - 博客園