1. 程式人生 > 其它 >基礎知識點 | 1018_指標和引用、野指標,printf函式的實現等知識點

基礎知識點 | 1018_指標和引用、野指標,printf函式的實現等知識點

1.指標和引用


定義

指標從本質上講就是存放變數地址的一個變數,在邏輯上是獨立的,它可以被改變

引用是一個別名,它在邏輯上不是獨立的,它的存在具有依附性,所以引用必須在一開始就被初始化,而且其引用的物件在其整個生命週期中是不能被改變的(自始至終只能依附於同一個變數)。


主要區別

  1. 引用必須被初始化,但是不分配儲存空間。指標不宣告時初始化,在初始化的時候需要分配儲存空間。
  2. 引用初始化後不能被改變,指標可以改變所指的物件。
  3. 不存在指向空值的引用,但是存在指向空值的指標。
  4. *sizeof* 引用”得到的是所指向的變數(物件)的大小,而“*sizeof* 指標”得到的是指標本身的大小;

傳參

  • 指標傳參

    • 本質上是值傳遞,它傳遞的是地址指向的值。在值傳遞的過程中,被調函式的形式引數作為被區域性變數進行處理(也就是在棧中開闢了記憶體空間來存放由主調函式放進來的實參值,從而成為實參的一個副本)。

    • 值傳遞的特點是被調函式對形參的任何操作都是作為區域性變數進行的,不會影響主調函式的實參變數。

  • 引用傳遞

    • 被調函式的形參雖然也作為區域性變數在棧中開闢了記憶體空間,但是這時存放的是由主調函式放進來的實參變數的地址,被調函式對形參的任何操作都被處理成間接定址(也就是通過棧中存放的地址訪問主調函式中的實參變數)。
    • 因此被調函式對形參做的任何操作都影響了主調函式中的實參變數

注意

如果想通過指標引數傳遞來改變主調函式中的相關變數,那就得使用指向指標的指標,或者指標引用


參考來源:

C++中指標和引用的區別(超詳細)



2.free() 和 野指標


一個指標連續被 free() 兩次,一定會報錯

  • free()的作用:釋放了指標所指向的記憶體區域,並未修改指標本身的地址值,指標仍指向原來的堆地址。(即,free前後,指標的地址不變)。free()函式只是告訴了作業系統,這塊記憶體我不再使用了,作業系統可以將該塊記憶體重新分配

  • free()之後發生了什麼:該指標變成了一個野指標(野指標指向一個已刪除的物件或未申請訪問受限記憶體區域的指標),如果需要再次使用該指標,需要將它置空


野指標

  1. 野指標是指程式設計師或操作者不能控制的指標。野指標不是NULL指標,而是指向“垃圾”的指標。

  2. 造成“野指標”的原因主要有

    • 指標變數沒有初始化。任何指標變數剛被建立時不會自動成為NULL指標,它的預設值是隨機的,它會亂指一氣。在初始化的時候要麼指向合法的指標,要麼指向NULL。
    • 指標變數被free或delete之後,沒有設定為NULL。它們只是把指標所指的記憶體給釋放掉,但並沒有把指標本身幹掉。通常會用語句if (p != NULL)進行防錯處理,然後if語句起不到防錯作用,因為即便p不是NULL指標,它也不指向合法的記憶體塊。
    • 指標操作超越了變數的作用範圍。所以要注意指標的生命週期。

參考來源:

C語言之free函式及野指標



3.printf函式的實現·


printf 函式的函式體:

int printf(const char *fmt, ...) 
{ 
    int i; 
    char buf[256]; 
	
    // printf引數中的第一個引數地址
    va_list arg = (va_list)((char*)(&fmt) + 4); 
    // 返回要打印出來的字串長度
    i = vsprintf(buf, fmt, arg); 
    // 將buf中的i個元素的值寫到終端中
    write(buf, i); 

    return i; 
} 

參考來源:

printf 函式實現的深入剖析



ps.1並不李姐,硬記


1. 字串除了存放在字元型陣列中之外,還可以存放在文字常量區
2. 函式過載是指在 同一作用域內,可以有一組具有 相同函式名,不同引數列表 的函式
   過載函式呼叫的依據是 函式名、引數型別、引數個數 
3. 行內函數在編譯時是將該函式的目的碼插入每個呼叫該函式的地方


ps.2值得記錄的題


1. 對於下面程式碼段,正確的賦值語句()
   char a[5],*p=a;
   
B. a="abcd";	// a 是用來標記陣列首地址,本身不佔執行時程式的空間,是不可修改的左值
C. *p="abcd";	// *p 就是 a[0],無法將字串賦值給一個字元

  • 陣列名 是 能隱式轉換成指向首元素的指標型別右值,大部分時候可以被看作指向陣列首地址的指標。除了以下兩種情況
    • sizeof(a)的結果並不是4(指標大小),而是5(1位元組 * 5)
    • &a,可以用一個指標來接受&a的結果

參考來源:

c中,陣列名跟指標有區別嗎?