首頁>Club>
聽說很難,實際上呢?
36
回覆列表
  • 1 # 程式設計老大叔

    C語言指標就是這門語言的靈活,說難學,那肯定是有難度的,畢竟這是業界公認的。但是如果你熟練掌握了指標的話,它又將會成為你手中的一柄利器。下面就詳細的分享一下指標該如何深入的去理解它以及如何熟練的應用它

    理解指標

    首先,你需要掌握兩個運算子“*”和“&”;

    “&”運算子:取物件在記憶體中的地址

    “*”運算子:取記憶體中地址上的物件(值);

    大家一定要深刻的理解上面兩個運算子,然後才能去進一步理解指標;

    int a = 100 ;這一行程式碼我想大家都沒問題。那麼“&a”返回的就是物件(變數)a在記憶體中的地址,它是一個16進位制數。

    然後用“*”號去a的地址去取物件:“*(&a)”,,就能取到物件a,也就就是100 ;

    接下來進入重點了,指標,本身也是一個變數(物件),它本身佔用記憶體,但是它只存地址(別人的地址),它存的誰的地址我們就稱它為指向誰的指標;

    int* p = &a ;int* p_2 = new int(200) ;先不管他的型別申明,只看變數本身p和p_2。前面講到指標存放的是物件的地址,那麼可以理解為指標是一個地址變數,那麼賦值的話就需要也賦一個地址給它一個地址。int* 和char*都可以表示地址型別,它們的區別就是地址所存的值得型別不同,一個是存整型,一個是存字元型;

    對指標取值的話,就是用“*”號,後面接物件地址,也就是指標變數,所以*p和*p_2就分別是a和200;

    指標的運用

    指標並不是C/C++獨有的,像C#和java等其實也是有指標的,只不過都被語言本身用其他的方式替代和封裝了一般程式設計師接觸不到,C/C++就不一樣,它是直接將指標暴露給開發者,因為大部分牽涉到指標的都與記憶體有關,而計算機記憶體很重要,萬一出什麼問題可能系統都會崩潰,下面就簡單來看一下程式在執行時指標與記憶體之間到底是個什麼樣的關係:

    先看一段程式碼:

    #include <stdio.h>

    #include <string>

    #include <iostream>

    #include <time.h>

    using namespace std;

    class people

    {

    public:

    people();

    ~people();

    string Name ;

    int age ;

    bool sex ;

    char info[1024] ;

    void run(){}

    void eat(){}

    private:

    };

    people::people()

    {

    }

    people::~people()

    {

    }

    int main()

    {

    people* p1 = new people();

    cout<<p1<<endl;

    cout<<&p1<<endl;

    cout<<sizeof(p1)<<endl;

    cout<<sizeof(*p1)<<endl;

    system("pause");

    return 0 ;

    }

    直接執行看結果:

    分析

    接下來來一一進行分析:

    首先people* p1 = new people();這一句是類的一個例項化,系統會給people例項化一個物件*p並且給它在堆上開闢空間,注意是在堆上,開闢的空間用來儲存物件的資料。資料包括哪些?就是物件的屬性和虛擬函式指標,但是函式並不儲存在各物件中。因此run()和eat()方法是不存在物件*p指向的記憶體處的。

    cout<<p1<<endl;輸出的是00279360,這是一個地址,是系統給new people()物件分配的地址。

    cout<<&p1<<endl;輸出的是0012FD90,這也是地址,但這是指標變數p本身的地址。

    cout<<sizeof(p1)<<endl;

    cout<<sizeof(*p1)<<endl;

    透過這兩個輸出就能有更清晰的認識了,p1本身只佔用4個位元組的空間,而它所指向的物件的地址所佔的空間就很大,等於類中所有資料型別所佔空間之和。

    接下來在main函數里寫一點邏輯:

    圖解

    我們來看一下程式執行時間,指標和記憶體是怎麼工作的。這裡畫一個圖給大家:

    程式在執行時,資料主要是儲存在棧、堆、程式碼區、全域性區。程式碼區主要就是存程式碼中出現的一些字元常量、方法等,比如這裡程式碼中給物件的Name屬性賦的值“xiaoli”之類的都是存在此處,然後我們透過new出來的物件,都是由堆透過計算好類中各屬性所需空間然後開闢出來的。這裡p3不是透過new開闢出來的,所以他是存在棧上的並且地址是固定的,是不能更改的,而p1和p2是能更改的。

    改變地址

    如此,我們三個物件互相賦值後會發生什麼呢?

    對比程式碼和輸出結果我們發現了什麼?賦值後p1和p2本身的地址並無改變,但是他所指向的記憶體都程式設計p3所在的記憶體了。下面用圖解給大家看一下:

    改變地址的值

    如果我將程式碼中的 p2 = &p3;換成*p2=p3呢?我們看下輸出結果:

    造成這種情況的原因,其實這就牽涉到指標的兩種賦值問題:一種是改變指向的地址,一種是改變本身指向地址的值p2 = &p3是改變指向地址,*p2=p3是改變指向地址的值。

  • 中秋節和大豐收的關聯?
  • 克萊湯普森朋友在友誼賽被呂曉明犯規,最後憤怒摔水瓶離開,你如何看待?