嵌入式八股文篇_第1頁
嵌入式八股文篇_第2頁
嵌入式八股文篇_第3頁
嵌入式八股文篇_第4頁
嵌入式八股文篇_第5頁
已閱讀5頁,還剩208頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

目錄TOC\o"1-3"\h\u面試必備 11運算符 11()[].-> !~++--&*/%*+-<<>>==><&|^&&||?:=+=-=, 11一、關(guān)鍵字篇 131. Continue 132. Break 133. Return 144. Goto 145. Volatile(編譯優(yōu)化階段) 156.Struct(結(jié)構(gòu)體)(C和C++區(qū)別,求結(jié)構(gòu)體大小,使用的注意事項) 157.class和struct的區(qū)別? 168.Union(聯(lián)合體) 162.聯(lián)合體union和結(jié)構(gòu)體struct的區(qū)別: 163.聯(lián)合體一般可以用來判斷大小端問題: 164.大小端轉(zhuǎn)換問題: 175.計算占用空間大小問題: 189.Enum 1910.Typedef 191.#define和typedef的區(qū)別(宏,關(guān)鍵字,預(yù)處理,編譯,檢查) 19注意#define和typedef定義指針的區(qū)別 20typedefint(*funtion)()//表示函數(shù)指針,重新命名為funtion 2011.Const(C中的變量:局部,函數(shù)形成,返回值,指針,typedef的區(qū)別,數(shù)組大小定義,caseC++:常函數(shù),常對象) 2012.Extern(鏈接階段) 2113.Register 2214.Auto 2215.Static(c語言:變量、函數(shù) C++:類中變量、類中靜態(tài)成員函數(shù)) 221.定義變量 222.定義函數(shù) 253.定義類中的靜態(tài)成員變量(不能在類里面初始化,不占類內(nèi)存空間,必須定義才能使用) 254.定義類中的靜態(tài)成員函數(shù)(只能訪問靜態(tài)成員變量) 2616.Swicthcase 2617.Dowhile 2618.Sizeof 261.Sizeof()和strlen()的區(qū)別 262.求指針大小 273.計算數(shù)組大小 274.如何不使用sizeof求數(shù)據(jù)類型字節(jié)的大小 27#definemysizeof(value)(char*)(&value+1)-(char*)(&value) 275.strlen(“\0”)=?sizeof(“\0”); 276.sizeof(a++) 287. 計算字符數(shù)組大小 288.sizeof(void) 2819.New/mallocdelete/free(指明大小,返回值,初始化) 2820.左值和右值是什么? 2821. 什么是短路求值 2922.++a和a++區(qū)別 3023.局部變量能不能和全局變量重名? 3124. gets和scanf函數(shù)的區(qū)別(空格,輸入類型,返回值) 3225. C語言編譯過程中,volatile關(guān)鍵字和extern關(guān)鍵字分別在哪個階段起作用? 3226. Printf()函數(shù)的返回值 3227.C語言中不能用來表示整常數(shù)的進制是二進制 3328.char*str1=“hello”和charstr2[]=“hello” 33二.內(nèi)存篇 341. 內(nèi)存分配有幾種方式: 342. 靜態(tài)全局存儲區(qū) 343. 堆上分配 342. 堆和棧有什么區(qū)別(申請方式、效率、方向) 343.棧在c語言中有什么作用 354.c++的內(nèi)存管理是怎樣的 355.什么是內(nèi)存泄漏 356.如何判斷內(nèi)存泄漏(如何減少內(nèi)存泄漏) 357. 字節(jié)對齊問題 368.C語言函數(shù)參數(shù)壓棧順序是怎樣的 369.C++如何處理返回值 3610.棧的空間值最大是多少 3711. 在1G內(nèi)存的計算機中能否malloc(1.2G)?為什么? 3712.strcat、strncat、strcmp、strcpy哪些函數(shù)會導(dǎo)致內(nèi)存溢出?如何改進 3713.malloc、calloc、realloc內(nèi)存申請函數(shù) 3714. 內(nèi)存泄漏(補充) 38三、指針和數(shù)組 39難點在于:一、二維數(shù)組的初始化,數(shù)組名的加法和&數(shù)組名的加法,指針數(shù)組和數(shù)組指針和一、二維數(shù)組的關(guān)系 391.什么是指針? 392.什么是指針的類型? 393.什么是指針?biāo)赶蝾愋?394.指針的值或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址 395.指針本身所占據(jù)的內(nèi)存區(qū) 398. 函數(shù)指針 406.指針的運算 407.認識這些指針運算指針的自加 419. 指針數(shù)組 4210. 數(shù)組指針和一維數(shù)組 4311. 指針函數(shù) 4312.指針和數(shù)組的區(qū)別?(類型、賦值、內(nèi)存、字節(jié)大小、修改內(nèi)容) 4413.什么是野指針?如何產(chǎn)生?如何避免? 4414.什么是智能指針 4515.智能指針的內(nèi)存泄漏問題是如何解決的? 4512. 數(shù)組名num/&num的區(qū)別 4513. 二級指針和指針引用 4521.指針和數(shù)組的使用 4622.有了指針為什么還需要引用 4623.使用指針的好處 4624.指針常量、常量指針、指向常量的常量指針 4625.指針和引用的異同,如何轉(zhuǎn)換 4726.sizeof(數(shù)組名)和sizeof(&數(shù)組) 4827. 數(shù)組下標(biāo)是負數(shù)的情況 4828.二維數(shù)組 4829.指針減指針 4930.數(shù)組作為參數(shù)傳遞 4931. 數(shù)組初始化 5032. 調(diào)用Free釋放內(nèi)存后,指針還能用嗎 5033. 函數(shù)指針 5144. 指針不能加指針 5145. 指針作為函數(shù)參數(shù)傳遞問題 5146.空指針的指向問題 5347.數(shù)組聲明和引用的下標(biāo) 5448. 二維數(shù)組和數(shù)組指針 54四、預(yù)處理 561.預(yù)處理器標(biāo)識#error的目的是什么? 562.頭文件中#ifndef#define#endif 563.#define和const 564.typedef和define(原理、作用域,對指針操作不同) 575.define的一些坑(缺點): 576.#include<頭文件>,#include”頭文件”的區(qū)別 577.定義一個常數(shù),用以表明一年有多少秒(忽略閏年) 588.簡述C++從代碼到可執(zhí)行二進制文件的過程 589.寫一個標(biāo)準(zhǔn)宏MIN, 5910.#definesqort(a)

((a)*(a)) 5911. 對指針的操作 5912. 在頭文件中是否可以定義靜態(tài)變量 6013. #和##的作用 6014. 使用宏求結(jié)構(gòu)體的內(nèi)存偏移地址 6015. 枚舉和define區(qū)別 6016. const和define區(qū)別 6117. typedef和define區(qū)別 6118. 宏函數(shù)和內(nèi)聯(lián)函數(shù)的區(qū)別 6119. 如何判斷一個整數(shù)是有符號還是無符號? 61五、函數(shù) 621.說說內(nèi)聯(lián)函數(shù)和宏函數(shù)的區(qū)別(本質(zhì),效率,檢查) 622.內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別(尋址,復(fù)制) 623.為什么析構(gòu)函數(shù)必須是虛函數(shù)? 624.為什么C++默認的析構(gòu)函數(shù)不是虛函數(shù) 655.靜態(tài)函數(shù)和虛函數(shù)的區(qū)別? 656.重載和重寫(覆蓋) 657.虛函數(shù)表具體怎么實現(xiàn)運行是多態(tài)? 668.構(gòu)造函數(shù)有幾種,分別什么作用 669.只定義析構(gòu)函數(shù),會自動生成哪些構(gòu)造函數(shù) 6810.說說一個類,默認會生成哪些函數(shù) 6811.說說C++類對象的初始化順序,有多重繼承情況下的順序 6912. select函數(shù) 6913.Forkwaitexec函數(shù) 7214.selectepollpoll函數(shù)區(qū)別 7315.變參函數(shù)的實現(xiàn) 7416. 字符輸入函數(shù) 7417. fseek函數(shù) 7418. 文件位置函數(shù) 7419. 處理信號的函數(shù) 7520. Scanf函數(shù) 7521. printf()函數(shù)和scanf()函數(shù)中的* 75六、面向?qū)ο?761.什么是面向?qū)ο?762.面向?qū)ο蠛兔嫦蜻^程的區(qū)別 763.面想對象的三大特征 764.什么是深拷貝?什么是淺拷貝? 785.什么是友元? 786.基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)能不能被繼承? 787.什么函數(shù)不能聲明為虛函數(shù) 788. vector的底層實現(xiàn) 799. vector和list的區(qū)別有什么 7910. 說一說vector擴容時發(fā)生了什么 7911. 刪除元素導(dǎo)致兩者迭代器發(fā)生什么變化 8012. 如何理解迭代器 8013. 容器的迭代器時由什么組成的 8014. 假如給你一個class,讓你去用class去實現(xiàn)一個智能指針,你會怎么做? 8015. STL中迭代器有什么用?有指針為何還有迭代器 8016. STL中迭代器是如何刪除元素 8117. map和set有什么區(qū)別?區(qū)別又是怎么實現(xiàn)的? 8118. STL的allocator有什么作用 8119. STL中的MAP數(shù)據(jù)如何存放的 8220. STL中的map和unordered_map有什么區(qū)別 8221. STL的resize和reserver的區(qū)別 8222. 為什么基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)不能被繼承 8223. C++中如何阻止一個類被實例化 8224. 純虛函數(shù)指的是什么? 8225. C++中哪些情況只能初始化列表,而不能賦值? 8326. 沒有參數(shù)的函數(shù)能不能被重載? 8327. 虛函數(shù)表建立時間 84七、數(shù)據(jù)結(jié)構(gòu)與算法 84數(shù)組篇 881.求兩數(shù)之和: 882. 三數(shù)之和 903.最小連續(xù)數(shù)組長度之和>滑動窗口 924.最大子數(shù)組和 935.原地移除元素 956.【26】.刪除有序數(shù)組中的重復(fù)項 977.合并兩個有序數(shù)組 988.尋找數(shù)組的中心下標(biāo) 999.有序數(shù)組的平方 1001. 排序 1021)直接插入 1022)希爾排序>直接插入的升級版 1031) 冒泡排序 1052) 快速排序 1071) 直接選擇 1082)堆排序 109隊列篇 1141.順序隊列 1152.循環(huán)隊列的相關(guān)計算 1153.鏈?zhǔn)疥犃?1184. 雙端隊列 119鏈表 120二叉樹 121查找 121八、操作系統(tǒng) 1221.什么是進程?什么是線程? 1222.進程、線程、協(xié)程的區(qū)別? 1223.何時使用多進程?何時使用多線程?(考慮優(yōu)缺點) 1234.創(chuàng)建進程的方式? 1235.進程有幾種狀態(tài)? 1236.進程間通信方式有哪些? 1247.進程間通信的選擇 1258、什么是僵尸進程、孤兒進程、守護進程? 1259.僵尸進程有什么危害? 12510.線程間通信方法有哪些? 12511.說說線程,進程同步方式有哪些? 12612.什么是內(nèi)核線程和用戶線程? 12613. 進程調(diào)度算法即策略有哪些? 12614.有搶占式和非搶占式的區(qū)別 12615.并發(fā)和并行 12616.進程間的通信中的管道通信實現(xiàn)原理是什么: 12717.說說什么死鎖,產(chǎn)生的條件,如何解決? 12818.單核機械上寫多線程程序,是否考慮加鎖,為什么? 12919.互斥鎖機制,互斥鎖和讀寫的區(qū)別? 12920.說說什么是信號量,有什么作用? 12921.進程、線程的中斷切換的過程是怎樣的? 12922.多線程和單線程有什么區(qū)別,多線程編程要注意什么,多線程加鎖需要注意什么? 13023.為什么要創(chuàng)建線程池?線程池的設(shè)計思路,線程池中線程的數(shù)量由什么確定? 13024.說說多路IO復(fù)用技術(shù)有哪些,區(qū)別是什么? 13025.說說多路IO復(fù)用技術(shù)有哪些,區(qū)別是什么? 13126.有名管道的通信: 14127.信號的常見知識 1411)信號的作用:用于通知接收進程有某種事件發(fā)生,除了用于進程間通信,還可以發(fā)送信號給自己 1412)常見信號: 1423)發(fā)送信號: 1424)進程可以對信號的操作: 1425)創(chuàng)建定時器: 14328.共享內(nèi)存 14329. 說說軟鏈接和硬鏈接的區(qū)別 1441) 定義不同: 1442) 限制不同 1443) 影響不同 14430.說說靜態(tài)庫和動態(tài)庫怎么制作及如何使用,區(qū)別是什么 144靜態(tài)庫的制作: 144動態(tài)庫的制作 145區(qū)別;什么時候加載,加載速度如何,內(nèi)存占用大小,執(zhí)行效率 14531.簡述GDB常見的調(diào)試命令,什么是條件斷點,多進程下如何調(diào)試 14532.簡述Linux系統(tǒng)態(tài)與用戶態(tài),什么時候會進入系統(tǒng)態(tài)? 14533. 什么是頁表,為什么要有? 14534. 簡述操作系統(tǒng)中malloc的實現(xiàn)原理 14635. 簡述操作系統(tǒng)中的缺頁中斷。 14736. 簡述mmap的原理和使用場景 14737.為什么使用虛擬內(nèi)存 14838.中斷的響應(yīng)執(zhí)行流程?聽說過頂半部和底半部嗎? 14839. busybox是什么? 14940. 什么是根文件系統(tǒng) 14941. 自旋鎖是什么?信號量是什么?二者有什么區(qū)別? 14942. 為什么堆的空間不是連續(xù)的? 14943.Linux內(nèi)核的組成部分(進程、內(nèi)存管理、文件系統(tǒng)、網(wǎng)絡(luò)接口) 15044.Linux系統(tǒng)的組成部分(內(nèi)核、shell、文件系統(tǒng)、應(yīng)用程序) 15045.線程的同步和互斥的區(qū)別和聯(lián)系 15046.常見命令 1511.解壓、壓縮命令 1512.查看內(nèi)存 1513.查看cpu 1514.psgrep|xxx 1515.修改文件權(quán)限 1516.查看內(nèi)核 1517.查看棧大小 15147.進程終止 15248.特殊進程 15250. 多線程中使用較多的函數(shù) 15250.pthread_cond_signal()和pthread_cond_broadcast() 15251.驅(qū)動里面為什么需要并發(fā)和互斥 15352. 軟中斷和硬中斷的區(qū)別 15352. fork和vfork的區(qū)別 15353.什么是虛擬內(nèi)存 15354.并發(fā)編程的三個概念 15455. 同步和異步 154網(wǎng)絡(luò)編程 1541.TCP頭部結(jié)構(gòu) 1542.請說一下socket網(wǎng)絡(luò)編程中客戶端和服務(wù)端用到哪些函數(shù)? 1551)服務(wù)器端函數(shù): 1552)客戶端函數(shù): 1553.UDP 1564.網(wǎng)絡(luò)四層模型 157應(yīng)用層http/TFTP 157傳輸層TCP/UDP 157網(wǎng)絡(luò)層IP/ICMP 1575.TCP如何保證可靠性? 1586.簡述TCP滑動窗口以及重傳機制 1587.簡述TCP慢啟動 1588.TCP建立連接和斷開連接過程? 159三次握手和四次揮手 1591)三次握手目的:是為了確認客戶端和服務(wù)器都能收發(fā) 1592)四次揮手: 1609.說說TCP2次握手行不行?為什么要3次 1618. 三次揮手可以嗎 16110.TCP連接和關(guān)閉的狀態(tài)轉(zhuǎn)移 16111.滑動窗口過小怎么辦? 16212.說說三次握手中每次握手信息對方?jīng)]有收到會怎樣? 16213.簡述TCP和UDP的區(qū)別,它們的頭部結(jié)構(gòu)是什么樣的(連接、可靠、阻塞、一對一、數(shù)據(jù)流、報文) 16314.簡述域名解析過程,本機如何干預(yù)域名解析 16315..說說什么是TCP粘包和拆包? 16316.如何解決粘包和拆包問題 16317.Tcp為什么比UDP可靠 16418.什么是HTTP 16419.http有什么特點? 16420.為什么客戶端最后還要等待2MSL 16421.什么時候應(yīng)該使用UDP? 16522.IPv4和IPv6的區(qū)別 1651)協(xié)議地址的區(qū)別 1652)地址解析協(xié)議 1663)身份驗證和加密 1664)數(shù)據(jù)包的區(qū)別 16623.IP地址: 16624. 字節(jié)序 167九.字符串函數(shù) 1681.求字符串長度 1682.字符串拷貝函數(shù) 1693.比較字符串是否相等 1694.拼接字符串函數(shù) 1705.memset 1716.字符串轉(zhuǎn)整數(shù) 1717.memcpy() 172十、通信協(xié)議篇 173USAR:異步全雙工,低-->高 1731)幀格式 1732)波特率:是指每秒可以發(fā)送多少位數(shù)據(jù) 1731.為什么一次只能發(fā)送一個字節(jié)?先發(fā)高位還是低位 1732.硬件連接 1743.串口通信存在的問題: 1744.RS232 1745.RS232和RS485的區(qū)別(抗干擾,距離,電平,設(shè)備連接) 175IIC協(xié)議(串行同步半雙工高>低) 1751.概念:串行的、半雙工的總線,主要應(yīng)用于近距離,低速的芯片之間的通信,IIC有兩根線, 1752.通信的過程: 1763.信號 1774.總線在空閑的時候SDA和SCL都處在高電平 1774.解決同步問題 1785.典型的IIC時序 179SPI(全雙工、同步串行,高>低) 1801.概念:spi是高速、全雙工、同步的串行通信總線,SPI至少有4根線, 1802.通信過程: 1813.極性和相位>確定了是上升沿發(fā)數(shù)據(jù)還是收數(shù)據(jù) 182IIC和SPI、串口區(qū)別 182IIC使用實例; 182SPI的使用 184CAN 188十一.硬件篇 1901.Cortex-M3和Cortex-M4可以同時支持小端模式和大端模式 1902.CPU內(nèi)部結(jié)構(gòu) 1903.CPU、內(nèi)存、虛擬內(nèi)存、硬盤的關(guān)系 1914. ARM結(jié)構(gòu)處理器分類 1915. 嵌入式微處理器和嵌入式DSP有什么區(qū)別? 1926. 存儲 1921. 通用計算機采用了Cache(高級緩沖存儲器)、主存儲器(RAM,內(nèi)存)、外部存儲器組成的三級存儲體系; 1922. 嵌入式系統(tǒng)存儲體系如下圖所示: 1923.嵌入式存儲器類型 1934.RAM 1935.ROM 1936.DDR 1947. Cache 1948.

簡述處理器在讀內(nèi)存的過程中,CPU核、cache、MMU如何協(xié)同工作?畫出CPU核、cache、MMU、內(nèi)存之間的關(guān)系示意圖加以說明 1957.常見的CPU指令集 1958. CPU的流水線工作原理 1959.嵌入式流水線工作有什么不同? 19510.uboot啟動過程做了什么事 19612. 中斷和異常 19613. DMA和中斷的區(qū)別 19614.中斷函數(shù)的注意 19615.為什么要向內(nèi)核傳參 19716.如何傳參 19717. uboot為什么要關(guān)閉caches 19718. 驅(qū)動申請內(nèi)存的函數(shù) 19819.AD轉(zhuǎn)換的原理? 198十一、Linux驅(qū)動篇 1991)移植需要做哪些工作 2012)uboot 2023)NXP就維護的2016.03這個版本的uboot,下載地址為: 2024)Uboot的區(qū)別 2025)uboot的初次編譯>正點原子 2021.首先在Ubuntu中安裝ncurses庫,否則編譯會報錯,安裝命令如下: 2022.創(chuàng)建目錄將開發(fā)板廠商提供的uboot拷貝過來 2023.解壓 2024.編譯 202可以寫成腳本文件 202第一條命令相當(dāng)于“makedistclean”,目的是清除工程 203當(dāng)輸入?或者help之后就會有命令幫助手冊 2041. uboot常見命令 2052. Mmc命令 205Mmc命令可以對sd卡以及emmc類的存儲煤質(zhì)進行操作 2053. 文件系統(tǒng)操作命令 20510)uboot啟動內(nèi)核過程 20511)編譯野火提供的uboot 2061)安裝依賴庫 2062)下載野火提供的uboot 2062)開始編譯 2083)燒錄 20912)移植官網(wǎng)的uboot 2091)下載uboot源碼 2092)解壓 2103)頭文件 2104)配置文件 2105)單板目錄和文件 2106)添加Kconfifig信息 2117)添加設(shè)備樹 212面試必備運算符()[].-> !~++--&*/%*+-<<>>==><&|^&&||?:=+=-=,優(yōu)先級,簡單記就是:!>算術(shù)運算符>關(guān)系運算符>&&>||>賦值運算符單目優(yōu)于雙目單目、條件、賦值是右左結(jié)合!表示取非,對于整形變量,只要不為0,使用

!

取反都是0,0取反就是1。就像

bool

只有真假一樣~取反,代表位的取反,對于整形變量,對每一個\t"/dxa572862121/article/details/_blank"二進制位進行取反,0變1,1變0。?:三目運算,源碼、補碼、反碼短路求值inta=5,b=3;!a&&(b++);printf("%d,%d\n",a,b);//5,3注意有符號和無符號的數(shù)運算有符號轉(zhuǎn)無符號,運算的時候是補碼運算,而不是源碼,打印的時候看輸出格式#include<stdio.h>intmain(){ inta=-7; unsignedintb=3; if((a+b)>0)//如果打印‘+’說明a+b>0,即有符號轉(zhuǎn)無符號運算的時候 { printf("+\n"); //+ } printf("%u\n",a+b);//4294967295 printf("%d\n",a+b);//-1return0;}/*-7源碼:10000000000000000000000000000111反碼:11111111111111111111111111111000補碼:111111111111111111111111111110016原碼:00000000000000000000000000000110反碼:00000000000000000000000000000110補碼:00000000000000000000000000000110計算;補碼111111111111111111111111111110010000000000000000000000000000011011111111111111111111111111111111*/8.%操作必須兩邊都是整數(shù)9.三目運算符 inta=2; intb=3; b=0?1:(++a); printf("%d\n",a); printf("%d\n",b);//33一、關(guān)鍵字篇Continue語句的作用是跳過本次循環(huán)體中余下尚未執(zhí)行的語句,立即進行下一次的循環(huán)條件判定,可以理解為僅結(jié)束本次循環(huán)。注意:continue語句并沒有使整個循環(huán)終止。只能用在循環(huán)語句Break只能用于循環(huán)語句或者開關(guān)語句會使最近包含break語句跳出在whilefor、循環(huán)中跳出本層循環(huán)在swich-case中跳出對應(yīng)的case如果for(){switchcase:break},for循環(huán)不受影響while(1) { switch(1) { case1:printf("1\n");break; } }如果是下面這樣的話:那就直接退出循環(huán)while(1) { switch(1) case1:printf("1\n");break; }在swich-case語句中如果沒有break語句那么就一定會執(zhí)行下面的語句

//首先去找有沒有對應(yīng)的num,如果沒有就執(zhí)行default語句,

//有就去執(zhí)行對應(yīng)的case語句,不論是case還是default,如果后面沒有break,那么是不會跳出swicth,會繼續(xù)執(zhí)行完下面的所有語句直到break;

intnum=250;

switch(num)

{

case50:num=50;

case100:num=200;

default:{num=250;printf("num%d\n",num);}//先找到default,發(fā)現(xiàn)沒有break就繼續(xù)執(zhí)行

case200:num=50;

}

printf("%d\n",num);break

語句用在循環(huán)體中,可結(jié)束本層循環(huán),continue語句用在循環(huán)體中,可結(jié)束本次循環(huán)Return結(jié)束當(dāng)前循環(huán),退出函數(shù),用在函數(shù)體中,返回特定值Goto無條件跳轉(zhuǎn)Volatile(編譯優(yōu)化階段)作用:告訴編譯器該變量是容易發(fā)生變化的,不能對該變量進行優(yōu)化,每次取值都必須從內(nèi)存中取值而不是直接去取之前在寄存器中的值例子:Volatileinta=20,b,c;b=a;C=a;代碼執(zhí)行流程如下;B=a;先從a的內(nèi)存中取值存放到寄存器,再把寄存器的值給存到b的內(nèi)存C=a;把寄存器的值給存到b的內(nèi)存可以看出編譯器對c=a這步進行優(yōu)化,不再執(zhí)行從a的內(nèi)存中取值,而是直接從寄存器中取值,如果這段時間內(nèi)a的發(fā)生變化,那么c就不能得到最新的值,這個時候就需要使用volatile告訴編譯器,不要對變量a優(yōu)化,每次都是從內(nèi)存中取a的值常見場景:1)多線程使用共享變量:因為多線程是多核操作,同時進行2)中斷:中斷程序會修改其他程序中使用的變量3)硬件寄存器:因為寄存器隨時會被修改,好比AD轉(zhuǎn)換的寄存器,隨時會因 為電壓變化而修改4)外部任務(wù)會修改變量6.Struct(結(jié)構(gòu)體)(C和C++區(qū)別,求結(jié)構(gòu)體大小,使用的注意事項)在c語言中結(jié)構(gòu)體是不允許有函數(shù),在c++中可以,C語言結(jié)構(gòu)體是不可以繼承,c++可以繼承C語言中結(jié)構(gòu)體的使用必須要用別名或者使用struct,不能直接使用例如: Structstudent { Intage; Intnum; Inrsex; } Typedefstructstudentstudent;//必須得別名才可以使用 或者在使用的時候加上struct,例如: structstudentstudent;4.訪問權(quán)限不同 在c中默認是共有,不可以修改權(quán)限,在c++中權(quán)限可以修改 5.初始化 在c中不可以初始化數(shù)據(jù)成員,c++可以初始化6.C++中空結(jié)構(gòu)體大小為1,C為07.class和struct的區(qū)別? 1)繼承權(quán)限:class是默認private,struct是public 2)訪問權(quán)限:class作為對象的實現(xiàn)體,默認是私有訪問,而struct是作為數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)體,是共有訪問 3)class可以用于定義模板,而struct不能8.Union(聯(lián)合體)2.聯(lián)合體union和結(jié)構(gòu)體struct的區(qū)別: 對于聯(lián)合體所有的成員都共享一塊內(nèi)存,而結(jié)構(gòu)體是所有變量內(nèi)存的疊加,需要考慮字節(jié)對齊問題,對于聯(lián)合體來說,只要你修改里面的成員的數(shù)據(jù)就會修改其他成員的數(shù)據(jù),而結(jié)構(gòu)體的成員數(shù)據(jù)是不影響的3.聯(lián)合體一般可以用來判斷大小端問題: 大端字節(jié)序:高字節(jié)存放在低位地址,低字節(jié)存放在高地址 小端字節(jié)序:低字節(jié)存放在低位,高字節(jié)存放在高位使用聯(lián)合體判斷大小端問題: 例子:unionmy{

short

t;

charb[2];};typedefunionmy

MY;

intmain(){

MYtest;

test.t=0X0102;

if(test.b[0]==0x01&&test.b[1]==0x02)

{

printf("這是大端字節(jié)序\n");

printf("%x\n",test.b[0]);

printf("%x\n",test.b[1]);

}

if(test.b[0]==0x02&&test.b[1]==0x01)

{

printf("這是小端字節(jié)序\n");

printf("%x\n",test.b[0]);

printf("%x\n",test.b[1]);

}

return0;}4.大小端轉(zhuǎn)換問題: 這里主要是位移操作 比如對于一個32位進行大小端轉(zhuǎn)換: 思路: 把0-7位移動到24-31 8-15位移動到16-23 16-23位移動到 8-15位 24-31位移動到0-7 //32位大小端交換intswap(intvalue){

value=((value&0x000000ff)<<24)|

((value&0x0000ff00)<<8)|

((value&0x00ff0000)>>8)|

((value&0xff000000)>>24);

returnvalue;} 5.計算占用空間大小問題:對于不同位的操作系統(tǒng),個別數(shù)據(jù)類型數(shù)據(jù)大小不一樣,Long和unsignedlong在32位中是4個字節(jié)在64位中是8個字節(jié) 計算的時候需要考慮字節(jié)對齊問題:所占空間必須是成員變量中字節(jié)最大的整數(shù)倍每個變量類型的偏移量必須是該變量類型的整數(shù)倍對于聯(lián)合體,由于所有變量都是共用一塊內(nèi)存,還需注意數(shù)組占用最大內(nèi)存例如:Typedefunion{doubleI;intk[5];charc;}DATE;在聯(lián)合體中成員變量最大為double為8個字節(jié),所以最終大小必須是8的整數(shù)倍;又因為聯(lián)合體是共占內(nèi)存空間,即int*5=20字節(jié),所以最終為24個字節(jié)Typedefstructdata{intcat;DATEcow;doubledog;}too;求sizeof(too);解:在結(jié)構(gòu)體里面聯(lián)合體為24,聯(lián)合體的最大類型為8字節(jié),所以聯(lián)合體的起始位置必須滿足偏移量為8的倍數(shù),計算如下:Cat:1-4,DATEcow8+24Doubledog32+8=40//聯(lián)合體的計算公式://最終的大小得是結(jié)構(gòu)體中的類型的最大長度的整數(shù)倍,并且能容下所有類型uniondate{

chara;

doubleb[3];

charc;};typedefuniondateDATE;/*結(jié)構(gòu)體的計算:1.最終的大小得是結(jié)構(gòu)體中的類型的最大長度的整數(shù)倍2.除了結(jié)構(gòu)體中的聯(lián)合體外,其他類型的偏移量必須是該類型的整數(shù)倍3.如果里面有聯(lián)合體,該聯(lián)合體的起始位置要滿足該聯(lián)合體的里面的最大長度類型的偏移量*/structtest{

chara;//1

DATEd;//8+24

charb;//33

charc;//34};//最終40typedefstructtestTEST;intmain(){

printf("%ld\n",sizeof(DATE));//24

printf("%ld\n",sizeof(TEST));//40

return0;}9.Enum里面的變量會自加10.Typedef1.#define和typedef的區(qū)別(宏,關(guān)鍵字,預(yù)處理,編譯,檢查)#define是C語言中定義的語法,是預(yù)處理指令,在預(yù)處理時進行簡單而機械的字符串替換,不作正確性檢查,只有在編譯已被展開的源程序時才會發(fā)現(xiàn)可能的錯誤并報錯。typedef是關(guān)鍵字,在編譯時處理,有類型檢查功能。它在自己的作用域內(nèi)給一個已經(jīng)存在的類型一個別名,但不能在一個函數(shù)定義里面使用typedef。用typedef定義數(shù)組、指針、結(jié)構(gòu)等類型會帶來很大的方便,不僅使程序書寫簡單,也使意義明確,增強可讀性。注意#define和typedef定義指針的區(qū)別 #definemyptrint*p myptra,b;//a是int*a,b是intb typedefint*myptr; myptra,b;//a是int*a,b是int*b補充:int*p,q表示p是指針變量,q是int變量typedefint(*funtion)()//表示函數(shù)指針,重新命名為funtion11.Const(C中的變量:局部,函數(shù)形成,返回值,指針,typedef的區(qū)別,數(shù)組大小定義,caseC++:常函數(shù),常對象)定義變量,表示該變量是個常量,不允許修改例如:constinta=100;錯誤:a=200;修飾函數(shù)參數(shù),表示函數(shù)體內(nèi)不能修改該參數(shù)的值修飾函數(shù)的返回值constchargetstr()const修飾的常見:Constinta;intconsta;是一樣的都是修飾變量a為常量Const*inta;intconst*a;修飾的是這個指針指向的內(nèi)容不允許修改,這個指針的地址可以改變常量指針I(yè)nt*Consta;修飾的指針,表示這個指針的地址不可以修改,地址的內(nèi)容可以修改指針常量Constint*consta;表示指針的地址不可以修改,內(nèi)容也不可以修改const修飾函數(shù)在c++的類中是不能Virtua虛函數(shù)constn=3;假設(shè)constn=3;Intnum[n]={1,2,3}問是否正確/錯誤:在c語言中n并不是真正意義上的常量,它還是變量 ,對于數(shù)組來說必須要開辟一個準(zhǔn)確的數(shù)組大小,C++中是可以編譯過去。

intn=3;

intnum[n]={1,2,3};//這樣也是錯誤的,數(shù)組必須是確定的注意:如果數(shù)組不初始化是沒有報錯的intn=3;

intnum[n];引申:switchcasen:也是不可以的所以在寫代碼的時候如果想要定義個常量最好是使用#define而不要使用const 7.在C++類中有常函數(shù)的概念比如在類中定義如下函數(shù):Voidfun()const{}像這種就是常函數(shù),這種函數(shù)只能讀取類中數(shù)據(jù),不能修改8.常對象常對象只能調(diào)用常函數(shù)9.const修飾的變量存放位置對于const修飾的局部變量:存放在棧中,代碼結(jié)束就會釋放,在C語言中可以通過指針修改里面的值對于const修飾的全局變量(已初始化的)存放在只讀數(shù)據(jù)段,不可以通過指針修改里面的值,未出示化的存放在.bss12.Extern(鏈接階段)聲明外部變量:(保存在數(shù)據(jù)段) 在文件a.c定義和聲明變量a,inta=20;//這里會建立存儲空間 通過extern在b.c文件里面聲明a之后就可以使用,記住不能初始化 Externinta;//正確 Externinta=30;//錯誤 注意:如果想要定義一個變量被其他文件使用,即定義一個全局變量,這個變量不能定義在頭文件里面,然后在需要調(diào)用該變量的.c文件里面extern聲明該變量是不可以的,編譯期會報錯:multipledefine多個定義,正確做法如下: 在main.c文件里面定義變量intgoble為全局變量, 在fun.c文件里面externintgoble;即可該作用主要是告訴編譯器我在其他文件定義了變量a,并且分配了空間,不再為該變量申請空間聲明外部外部函數(shù)聲明外部一樣Extern“C” 該做用是實現(xiàn)在c++中調(diào)用c語言代碼,告訴編譯器這部分代碼要是有C編譯 13.Register 存在寄存器里面,即cpu,該值不能取地址操作,并且是整數(shù),不能是浮點數(shù)14.Auto 一般情況下我們沒有特別說明的局部變量都是默認為auto類型,存儲在棧中15.Static(c語言:變量、函數(shù) C++:類中變量、類中靜態(tài)成員函數(shù))1.定義變量 靜態(tài)全局變量>作用域只能作用域本文件,每次函數(shù)調(diào)用該變量都會被初始化 靜態(tài)局部變量>生命周期不會隨函數(shù)結(jié)束結(jié)束,直到程序結(jié)束,但是在函數(shù)外面不能使用該變量,只能在函數(shù)中使用,該變量是有記憶的,會記住上次的值,。該變量只被初始化一次 對于這兩種變量來說,如果初始化的會在數(shù)據(jù)段內(nèi),未初始化的在.bss段或者初始化為0,這兩種變量都會在程序結(jié)束才會釋放,只不過作用域不同,靜態(tài)局部變量只限定于函數(shù)中,但是該函數(shù)結(jié)束,該變量并沒有被干掉,靜態(tài)全局變量限定于本文件中先來看下沒有用static定義的變量aintgetdata(){

int

a=10;

a++;

printf("%d\n",a);

returna;}intmain(){

for(inti=0;i<10;i++)

getdata();

return0;}可以看出打印的都是11,說明每次函數(shù)結(jié)束變量a就結(jié)束生命周期,這就是局部變量我們再來看看有static修飾的變量a可以看出static修飾的局部變量是不會隨函數(shù)結(jié)束而結(jié)束,是保留記憶的,但是該變量只能在該函數(shù)中使用,雖然它存在,但是別人不能使用,因為他畢竟是局部變量,限定了作用域靜態(tài)局部變量和靜態(tài)全局變量的區(qū)別總結(jié)靜態(tài)全局變量和全局變量差不多,可以被初始化,也有記憶,但是卻被限定了只能在本文件中使用2.定義函數(shù) 在函數(shù)返回類型前加上static關(guān)鍵字,函數(shù)即被定義為靜態(tài)函數(shù)。靜態(tài)函數(shù)只能在本源文件中使用;也就是說在其他源文件中可以定義和自己名字一樣的函數(shù)3.定義類中的靜態(tài)成員變量(不能在類里面初始化,不占類內(nèi)存空間,必須定義才能使用) 在類中的靜態(tài)成員變量它即可以被當(dāng)做全局變量那樣存儲,但又被隱藏與類中,類中的靜態(tài)成員變量擁有一塊獨立的儲存空間,不會占用類中的空間,所有的對象都共享該靜態(tài)成員,也就是說,只要有對象改變了這個值,那么其他對象就會受影響,該數(shù)據(jù)可以使用this,也可以類中其他函數(shù)訪問 注意:靜態(tài)數(shù)據(jù)成員不能在類中初始化,在類中只是聲明,而不是定義,靜態(tài)數(shù)據(jù)必須要定義之后才能使用,實際上類定義只是在描述對象的藍圖,在其中指定初值是不允許的。也不能在類的構(gòu)造函數(shù)中初始化該成員,因為靜態(tài)數(shù)據(jù)成員為類的各個對象共享,否則每次創(chuàng)建一個類的對象則靜態(tài)數(shù)據(jù)成員都要被重新初始化4.定義類中的靜態(tài)成員函數(shù)(只能訪問靜態(tài)成員變量)靜態(tài)成員函數(shù)也是類的一部分,而不是對象的一部分。所有這些對象的靜態(tài)數(shù)據(jù)成員都共享這一塊靜態(tài)存儲空間注意:靜態(tài)成員函數(shù)不屬于任何一個對象,因此C++規(guī)定靜態(tài)成員函數(shù)沒有this指針(劃重點,面試題??迹<热凰鼪]有指向某一對象,也就無法對一個對象中的非靜態(tài)成員進行訪問,即不能在靜態(tài)函數(shù)里面使用this指針16.Swicthcase 注意: 1.switch里面不能是浮點數(shù)、double,可以是表達式,但是結(jié)果不能是浮點數(shù)或double 2.要注意case語句后面是否有break,如果沒有,就會從找到的case語句一直執(zhí)行到停止 3.case不能是”shshj”,可以是‘s’因為字符最終也是整數(shù),變量表達式也不行,反正這個東西必須是能確定的17.Dowhile 先do,再while判斷是否符合while里面的條件18.Sizeof1.Sizeof()和strlen()的區(qū)別 首先sizeof是關(guān)鍵字,strlen是函數(shù),sizeof用來計算占用內(nèi)存大小,strlen是用來計算字符串的長度, 特別是對于需不需要包含\0問題:Sizeof是需要給\0計算空間的,strlen是不需要,sizeof是在編譯的時候計算的,而strlen是在運行的時候計算2.求指針大小 在32位機器下,對于sizeof(指針變量)都是4個字節(jié),比如 Int*a; Sizeof(a);引申:求引用大小 Sizeof(char&)//1引用大小和數(shù)據(jù)類型有關(guān)3.計算數(shù)組大小sizeof計算的是數(shù)組的大小即數(shù)據(jù)類型*[]strlen計算的是字符串長度intnum[5]={1,2,3,4};printf("%ld\n",sizeof(num));//20

charstr[10]={"hello"};printf("%ld\n",strlen(str));//5printf("%ld\n",sizeof(str));//104.如何不使用sizeof求數(shù)據(jù)類型字節(jié)的大小 #definemysieof(value)(char*)(&value+1)-(char*)(&value) #definemysizeof(value)(char*)(&value+1)-(char*)(&value)5.strlen(“\0”)=?sizeof(“\0”);

printf("%d\n",sizeof("\0"));//2因為這里有\(zhòng)0\0printf("%d\n",strlen("\0"));//0 printf("%d\n",sizeof("\0"));//2 printf("%d\n",strlen("\0"));//0 printf("%d\n",sizeof('\0'));//4 //printf("%d\n",strlen('\0'));//報錯 6.sizeof(a++)

inta=2;

printf("%d\n",sizeof(a++));//4

printf("%d\n",a); //a=2注意:對于sizeof只會求所占內(nèi)存大小,不會進行表達式運算計算字符數(shù)組大小 charch[]="hello"; charstr[10]={'h','e','l','l','o'}; printf("%d\n",sizeof(ch));//6 printf("%d\n",strlen(ch));//5 printf("%d\n",sizeof(str));//10 printf("%d\n",strlen(str));//58.sizeof(void)出錯或者為119.New/mallocdelete/free(指明大小,返回值,初始化) 1.首先new/delete是運算符,而malloc和free是函數(shù) 2.new先為對象申請內(nèi)存空間,讓后再調(diào)用構(gòu)造函數(shù)進行初始化,同理delete可以調(diào)用析構(gòu)函數(shù)釋放內(nèi)存,而malloc只是申請內(nèi)存空間并不能調(diào)用構(gòu)造函數(shù)進行初始化,同理free也只是釋放內(nèi)存 3.malloc的返回值需要強轉(zhuǎn)為自己申請的內(nèi)存指針,而new不需要 4.malloc需要指定申請內(nèi)存的內(nèi)存大小20.左值和右值是什么?左值是指出現(xiàn)在等號或者表達式左邊的變量,一般來說就是它的值可以改變,右值是指出現(xiàn)在等號的右邊的變量或者表達式,它重要特點是可讀通常下,左值可以做右值,右值不能做左值a++不能進行左值運算比如:i++=5;補充:數(shù)組名是常量不能給數(shù)組名賦值voidtest3(){

charstr[10];

str++;

//數(shù)組名是常量不能賦值該語句相當(dāng)于str=str+1也就是說不能左值

*str='0';}什么是短路求值例子:intmain(){

inta=2;

intb=3;

if(a>0||b++>2)//b++>3這個的優(yōu)先級:先進行判斷b>3,再b+1;

{

printf("%d\n",b);//b=3,//解釋:在if里面有||條件,只要滿足其中一個就認為滿足條件,就不再需要判斷另個語句,也就是說b++并沒有執(zhí)行

}

if(a<0||b++>2)

{

printf("%d\n",b);//b=4,//解釋:在if里面有||條件,只要滿足其中一個就認為滿足條件,就不再需要判斷另個語句,但第一個條件并沒有滿足,所以就會執(zhí)行b++

}

if(a>0&&b++>2)

{

printf("%d\n",b);//b=5,//解釋:在if里面有&&條件,只有滿足第一個條件才會去判斷剩下的條件,第一個條件滿足,所以就會執(zhí)行b++

}

if(a<0&&b++>2)

{

printf("%d\n",b);//b=5,//解釋:在if里面有&&條件,只有滿足第一個條件才會去判斷剩下的條件,第一個條件不滿足,也就是說b++并沒有執(zhí)行

}

printf("%d\n",b);

return0;}22.++a和a++區(qū)別a++是先把a賦值到一個臨時空間,再對a+1賦值給臨時變量,等運算結(jié)束后才返回臨時變量給a(參與運算的是自加之前的值)解析:i++相當(dāng)于i=i+1等號右邊的為右值,只能讀,不能寫,即右邊的i只能讀出放到一個臨時變量里面,在這個臨時變量里面進行+1操作之后,再賦值給等號左邊的i++a是先給a+1,直接對a賦值,不需要開辟臨時空間(參與運算的是返回值的引用)a++需要開辟空間,等運算完才返回值,所以效率比++a低/*做自加和后自加題目之前要先明白以下幾點:1.無論是前自加還是后自加都是函數(shù)調(diào)用,都有返回值,返回值就是我們需要用來運算的2后自加的返回值是自加前的值3.前自加的返回值是該變量的引用不是具體的數(shù)值,做運算的時候才確定(比如+-/%*)4.所有的運算都是返回值的運算比如:inti=1;printf("%d\n",++i/i--);左邊的++i的返回值是變量i的引用,這個時候i=2,右邊i--返回的是做--之前的數(shù)值即2,這個時候i=1,也就是說i的引用為1,即1/2=0*/23.局部變量能不能和全局變量重名? 能,局部變量會屏蔽全局變量,比如在一個函數(shù)里定義一個變量inta=2,在外面定義全局變量inta=1;那么在該函數(shù)里操作的是局部變量如果想使用全局變量,可以使用{externinta}形式gets和scanf函數(shù)的區(qū)別(空格,輸入類型,返回值) 1)gets函數(shù)可以接受空格,scanf遇到空格就會結(jié)束 2)gets函數(shù)僅用于讀入字符串;scanf為格式化輸出函數(shù),可以讀入任意C語言基礎(chǔ)類型的變量值,而不是僅限于字符串(char*)類型 3)gets的返回值為char*型,當(dāng)讀入成功時會返回輸入的字符串指針地址,出錯時返回NULL; scanf返回值為int型,返回實際成功賦值的變量個數(shù),當(dāng)遇到文件結(jié)尾標(biāo)識時返回EOFC語言編譯過程中,volatile關(guān)鍵字和extern關(guān)鍵字分別在哪個階段起作用? volatile預(yù)處理,因為代碼優(yōu)化是在編譯,extern在鏈接Printf()函數(shù)的返回值 假設(shè)1 inta=241; Printf(“%d\n”,a); printf的返回值是4,也就是說返回值是a數(shù)字的字符個數(shù)+\n 假設(shè)2 printf("%d\n",printf("%d",a));//2413 printf("%d\n",printf("%d\n",a));//2414多了\n注意空格也算27.C語言中不能用來表示整常數(shù)的進制是二進制 28.char*str1=“hello”和charstr2[]=“hello”數(shù)組名相當(dāng)于常量指針,只可以修改數(shù)組里面的元素,不可以修改數(shù)組的地址即不能str++字符指針相當(dāng)于是指針常量,不可以修改指向的地址的內(nèi)容,可以修改地址charstr[]="hello";

char*str1="hello";

//區(qū)別一數(shù)組名不可以自加,因為數(shù)組名是地址常量

//str++;

//str1++;

//區(qū)別二,數(shù)組里面的元素可以修改,str1指向的地址的內(nèi)容不可以修改

str[0]='W';

*str1='w';//段錯誤

//總結(jié):數(shù)組名就相當(dāng)于是常量指針,只可以修改里面的內(nèi)容,不可以修改指向的地址,字符指針相當(dāng)于是指針常量,不可以修改指向的地址的內(nèi)容,可以修改地址局部變量和全局變量同名的時候如何使用全局變量方法1:使用函數(shù),把全局變量包到里面,作為返回值方法2:使用{Extern}內(nèi)存篇內(nèi)存分配有幾種方式:棧上分配:在執(zhí)行函數(shù)之前,函數(shù)內(nèi)部的局部變量都可以在棧上創(chuàng)建,函數(shù)執(zhí)行完畢之后會自動釋放靜態(tài)全局存儲區(qū)全局變量和靜態(tài)變量堆上分配由程序員分配,好比new,free,mallocfree堆和棧有什么區(qū)別(申請方式、效率、方向)1.申請方式不同:棧是由操作系統(tǒng)自由分配和釋放,堆是由程序員手動申請釋放2.申請大小的限制:棧是向低地址申請的空間,一塊連續(xù)的內(nèi)存,也就是說,棧的大小和地址是由系統(tǒng)預(yù)先規(guī)定好的,如果申請的空間超過棧的剩余空間就會提示overflow堆的申請是向高地址擴張的,是不連續(xù)的內(nèi)存區(qū)域,這是由于系統(tǒng)使用鏈表來存儲的空閑內(nèi)存地址3.申請的效率 棧使用的是一級緩存,它們通常都是被調(diào)用時處于存儲空間中,調(diào)用完畢立即 釋放;堆則是存放在二級緩存中,速度要慢些題目:堆棧溢出一般是由什么原因?qū)е碌模?遞歸,動態(tài)申請內(nèi)存,數(shù)組訪問越界,指針非法訪問)答:1.函數(shù)調(diào)用層次太深。函數(shù)遞歸調(diào)用時,系統(tǒng)要在棧中不斷保存函數(shù)調(diào)用時的現(xiàn)場和產(chǎn)生的變量,如果遞歸調(diào)用太深,就會造成棧溢出,這時遞歸無法返回。再有,當(dāng)函數(shù)調(diào)用層次過深時也可能導(dǎo)致棧無法容納這些調(diào)用的返回地址而造成棧溢出。2.動態(tài)申請空間使用之后沒有釋放。由于C語言中沒有垃圾資源自動回收機制,因此,需要程序主動釋放已經(jīng)不再使用的動態(tài)地址空間。申請的動態(tài)空間使用的是堆空間,動態(tài)空間使用不當(dāng)造成堆溢出。3.數(shù)組訪問越界。C語言沒有提供數(shù)組下標(biāo)越界檢查,如果在程序中出現(xiàn)數(shù)組下標(biāo)訪問超出數(shù)組范圍,在運行過程中可能會內(nèi)存訪問錯誤。4.指針非法訪問。指針保存了一個非法的地址,通過這樣的指針訪問所指向的地址時會產(chǎn)生內(nèi)存訪問錯誤。3.棧在c語言中有什么作用 1.用來保存臨時變量,臨時變量包括函數(shù)參數(shù),函數(shù)內(nèi)部定義的臨時變量 2.多線程編程的基礎(chǔ)就是棧,棧是縮寫詞編程的及時,每個線程多最少有自己的專屬的棧,用來保存本線程運行時各個函數(shù)的臨時變量4.c++的內(nèi)存管理是怎樣的在c++中虛擬內(nèi)存分為代碼段、數(shù)據(jù)段、bss段、堆、共享區(qū)、棧代碼段:包括只讀存儲去和文本區(qū),其中只讀存儲區(qū)字符串常量,文本區(qū)存儲程序的機械代碼數(shù)據(jù)段:全局變量、靜態(tài)變量(全局、局部)BSS段:未初始化的全局變量和靜態(tài)變量(全局、局部),以及所有被初始化為0的全局變量和靜態(tài)變量堆:調(diào)用new/malloc申請的內(nèi)存空間,地址由低地址向高地址擴張映射區(qū):存儲動態(tài)鏈接庫以及調(diào)用mmap函數(shù)的文件映射棧:局部變量、函數(shù)的返回值,函數(shù)的參數(shù),地址由高地址向低地址擴張5.什么是內(nèi)存泄漏簡單來說就是申請了內(nèi)存,不使用之后并沒有釋放內(nèi)存,或者說,指向申請的內(nèi)存的指針突然又去指向別的地方,導(dǎo)致找不到申請的內(nèi)存,有什么影響:隨著程序運行時間越長,占用內(nèi)存越多,最終用完內(nèi)存,導(dǎo)致系統(tǒng)崩潰6.如何判斷內(nèi)存泄漏(如何減少內(nèi)存泄漏)1.良好的編碼習(xí)慣,使用內(nèi)存分配的函數(shù),一但使用完畢之后就要記得使用對應(yīng)的函數(shù)是否掉2.將分配的內(nèi)存的指針以鏈表的形式自行管理,使用之后從鏈表中刪除,程序結(jié)束時可以檢查改鏈表3.使用智能指針4.使用常見插件,ccmalloc內(nèi)存模型:字節(jié)對齊問題什么是字節(jié)對齊:需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個接一個的排放,這就是對齊常見就是求復(fù)合類型大小,比如結(jié)構(gòu)體、聯(lián)合體 為什么需要字節(jié)對齊需要字節(jié)對齊的根本原因在于CPU訪問數(shù)據(jù)的效率問題比如:8.C語言函數(shù)參數(shù)壓棧順序是怎樣的從右往左,并且內(nèi)存中棧是由高向低擴展,所以先入棧的是右邊并且地址是高位比如printf()函數(shù),也都是先打印最右邊9.C++如何處理返回值10.棧的空間值最大是多少Window是2MB,Linux是8MB使用ulimit-s在1G內(nèi)存的計算機中能否malloc(1.2G)?為什么?有可能,因為malloc是相進程申請?zhí)摂M內(nèi)存,與物理地址空間沒有直接關(guān)系12.strcat、strncat、strcmp、strcpy哪些函數(shù)會導(dǎo)致內(nèi)存溢出?如何改進13.malloc、calloc、realloc內(nèi)存申請函數(shù)申請堆內(nèi)存void*malloc(size_tsize);//申請size_t個字節(jié)內(nèi)存voidfree(void*ptr);//釋放內(nèi)存,但是指針還是可以用void*calloc(size_tnmemb,size_tsize);//申請nmemb快內(nèi)存,每塊size_t個字節(jié)void*realloc(void*ptr,size_tsize);//申請內(nèi)存,重新申請size_t字節(jié)內(nèi)存,void*reallocarray(void*ptr,size_tnmemb,size_tsize);說明:malloc()內(nèi)存未初始化,如果size為0,則malloc()返回NULL或一個稍后可以成功傳遞給free ()的唯一指針值。2.Realloc()如果size_t>原來的s申請的空間大小,比如原來是100個字節(jié),現(xiàn)在是150個字節(jié),那么就有以下兩種情況:原來100個字節(jié)后面還能放的下50個字節(jié),那么就在原來地址上增加50個字節(jié),返回的還是原來地址如果100個字節(jié)后面放不下50個字節(jié),那么就會重新找個地址開辟150個字節(jié)空間,把原來的地址數(shù)據(jù)拷貝過來,釋放掉原來地址空間,返回一個新的地址如果size_t<原來的s申請的空間大小,比如原來是100個字節(jié),現(xiàn)在是50個字節(jié),那么就會釋放掉后50個字節(jié)

int*p=(int*)malloc(sizeof(int)*25);

if(p==NULL)

{

return-1;

}

printf("malloc%p\n",p);

//p=(int*)realloc(p,10);//重新分配10個字節(jié)大小,刪除原來后面的90個字節(jié)

p=(int*)realloc(p,200);//重新分配200個字節(jié)大小,可能是在原來基礎(chǔ)上加100,也可能是重新開辟200

printf("malloc%p\n",p);3.calloc申請內(nèi)存空間后,會自動初始化內(nèi)存空間為0內(nèi)存泄漏(補充)內(nèi)存泄漏是指動態(tài)申請內(nèi)存,1)但是不用之后內(nèi)存沒有釋放掉,一直留在程序里,2)或者申請了內(nèi)存,指針又指向了別的地方1)不用之后內(nèi)存沒有釋放掉,一直留在程序里浪費voidfun(){

char*p=(char*)malloc(sizeof(int)*25);

if(p==NULL)

{

return-1;

}

/*

使用內(nèi)存

*/

/*

問題:

1.函數(shù)結(jié)束沒有調(diào)用free釋放內(nèi)存

*/

}2)申請了內(nèi)存,指針又指向了別的地方

char*p=(char*)malloc(sizeof(int)*25);

if(p==NULL)

{

return-1;

}

printf("malloc%p\n",p);

//malloc0x5573503ee2a0

p="hello";

printf("hello%p\n",p);

//hello0x55734f5eb00f//可以看出這里出現(xiàn)內(nèi)存泄漏://原本p指向使用malloc申請內(nèi)存的地址0x5573503ee2a0,后來又讓p指向字符串常量的地址0x55734f5eb00f,此時就找不到malloc的地址了三、指針和數(shù)組難點在于:一、二維數(shù)組的初始化,數(shù)組名的加法和&數(shù)組名的加法,指針數(shù)組和數(shù)組指針和一、二維數(shù)組的關(guān)系1.什么是指針?指針其實也是個變量,只不過這個變量里面存儲的是內(nèi)存地址2.什么是指針的類型?舉個例子:Int*a;指針類型為int*Char*c;指針類型為char*3.什么是指針?biāo)赶蝾愋团e個例子:Int*a;指針類型為intChar*c;指針類型為char4.指針的值或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址注意:這個指針的類型是什么?指針指的類型是什么?該指針指向了哪里?(重點注意)5.指針本身所占據(jù)的內(nèi)存區(qū)占用內(nèi)存的大小,在32為系統(tǒng)中無論是什么類型的指針都是4個字節(jié)函數(shù)指針首先是個指針,這個指針指向函數(shù)應(yīng)用場景:回調(diào)例如:Int(*fun)(int,int);實例:intmax(intx,inty){

intz;

if(x>y)

{

z=x;

}

else

{

z=y;

}

returnz;}intmain(){

int(*p)(int,int);//定義一個函數(shù)指針

inta,b,c;

p=max;//把函數(shù)的地址給指針

a=20;

b=30;

c=(*p)(a,b);//調(diào)用函數(shù)指針

printf("%d\n",c);

return0;}6.指針的運算例子1:int*ptr;//假設(shè)指針指向的地址是0x00000000Ptr++;//運算之后指針指向0x00000004注意P+1也是加4個字節(jié)因為int在32位系統(tǒng)中是32位,運算的時候是以單元為單位及一個int,即4個字節(jié)Char*p;P++;//地址偏移1注意:對于一級指針的++操作偏移量要看指針指向的是什么類型對應(yīng)二級指針偏移量,對于32系統(tǒng)是4個字節(jié),因為二級指針指向的類型就是指針,所以永遠是一個指針類型的大小例子2:#include<stdio.h>intmain(){chara[20]="You_are_a_girl";char*p=a;char**ptr=&p;printf("**ptr=%c\n",**ptr);ptr++;printf("**ptr=%c\n",**ptr);}在這個例子中是無法確定二級指針++之后指向的地址內(nèi)容,因為二級指針(ptr)指針指向的一級指針的地址,如果二級指針(ptr)++之后,那么就會指向一級指針的后4個字節(jié)(對于32位操作系統(tǒng)來說指針類型是4字節(jié)),至于這個地址里面是啥無從得知7.認識這些指針運算指針的自加*p++

*(p++)

(*p)++

*++p

++*p1.后++先不用管,即先把地址里面的值給別人,再去++,可以是地址或值(看括號是否包住*p,是則是值++),后++有三種如下:(*p)++地址前后都不會變化,變化的是地址里面的值,先賦值給別人,*P再++*(p++)和*p++一樣地址發(fā)生變化,先把*P賦值給別人,再++地址2.前++,先++操作,可以是++地址或者值,(++符號靠近p就是地址++,靠近*P就是值++),再把值給別人*++p地址發(fā)生改變,先把地址++,再把地址變化后的里面的值給別人++*p地址不發(fā)生變化,*P的值++之后再賦值給別人注意:指針++,到底加幾個字節(jié)要根據(jù)指針指向的類型決定,指針在32系統(tǒng)中永遠是4個字節(jié)舉例子:Int*a;//假設(shè)指針指向的地址0a++;//此時指針指向后移4個字節(jié),即指向4Char*b;//假設(shè)指針指向的地址0b++;//此時指針指向后移1個字節(jié),即指向1指針數(shù)組首先是個數(shù)組,這個數(shù)組里的元素是指針例如:int*p[4];inta[4]={1,2,3,4};p[0]=&a[0];printf("%d\n",*p[0]);數(shù)組指針和一維數(shù)組首先是個指針,這個指針指向數(shù)組例如:Int(*p)[4];//表示一個指向有4個int元素的數(shù)組的指針,所以p+1,加的是4個intintnum[8]={1,2,3,4,5,6,7,8}; int(*p)[4]; p=num; printf("%d\n",sizeof(p));//8因為p是指針,64位系統(tǒng)8個字節(jié) printf("%p\n",p);//0x7ffe11d8a4e0 printf("%p\n",p+1);//0x7ffe11d8a4f0//加的是指針指向的類型大小,這里指針指向的是有四個4int元素的數(shù)組,所以加的是16個字節(jié)如何求某個元素?比如求num[5]的元素表示如下:*(*(P+1)+1)其實你就把數(shù)組指針看成是二維數(shù)組就行,p+1,加的是一個一維數(shù)組的長度,*(p+1)就是二維變一維組數(shù),(*(P+1)+1)表示后移一個地址,*(*(P+1)+1)取出元素指針函數(shù)首先是個函數(shù),這個函數(shù)的返回值是個指針類型例如:Int*fun(intx,inty){}12.指針和數(shù)組的區(qū)別?(類型、賦值、內(nèi)存、字節(jié)大小、修改內(nèi)容)1.概念數(shù)組:是同種類型的集合指針:里面保存的地址的值2.賦值:同種類型指針之間可以直接賦值,數(shù)組只能一個個元素賦值3.存儲方式:數(shù)組是連續(xù)的一段空間,指針的存儲空間是不確定的4.修改內(nèi)容不同比如:charp[]=”hello”,我們可以執(zhí)行p[0]=‘s’操作原因是p是數(shù)組,可以使用下標(biāo)的方式進行修改數(shù)組內(nèi)容Char*p=“hello”執(zhí)行p[0]=‘s’是錯誤的,原因是p是指針,指向字符串常量,常量是不允許修改的5.所占字節(jié)不同指針永遠是4個字節(jié)在32為系統(tǒng)中,而數(shù)組是不固定的,要看數(shù)組的類型和元素個數(shù)13.什么是野指針?如何產(chǎn)生?如何避免?野指針:是指指針指向的地址是不確定的;原因:釋放內(nèi)存之后,指針沒有及時置空避免:初始化置NULL申請內(nèi)存后判空指針釋放后置NULL使用智能指針一般流程如下:Assert函數(shù):voidassert(intexpression);expression

--這可以是一個變量或任何C表達式。如果

expression

為TRUE,assert()不執(zhí)行任何動作。如果

expression

為FALSE,assert()會在標(biāo)準(zhǔn)錯誤stderr上顯示錯誤消息,并中止程序執(zhí)行。int*p1=NULL;//初始化置NULLp1=(int*)calloc(n,sizeof(int));//申請n個int內(nèi)存空間同時初始化為0assert(p1!=NULL);//判空,防錯設(shè)計free(p1);

p1=NULL;//釋放后置空14.什么是智能指針智能指針是個類,用來存儲指針(指向動態(tài)分配對象的指針)C++程序中使用堆內(nèi)存是非常頻繁的,堆內(nèi)存的申請和釋放由程序員手動管

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論