【C/C++和指標】深度解析—指標與數組 【精華】

來源:互聯網
上載者:User

一,引例子

二維數組可以使用指向數組的指標代替,而指標數組才可以用指向指標的指標代替。

#include<iostream>using namespace std;void main(){     char *a[]={"Hello","the","World"}; //指標數組     char **pa=a; //指向指標的指標     pa++;      cout<<*pa;}

 

類型確定的數組,元素的類型和元素的個數是確定的;數組退化為對應的指標,元素的類型保持一致;

所謂的二維數組只是數組的數組,因此二維數組不能退化為二級指標,而只能退化為指向一維數組的指標

例子:

#include <iostream.h> 
void main()

    int a[2][3];    //二維數組

    int **p=a;      //二維數組不能退化為指向指標的指標

請問為什麼是錯誤的??(請不要說數組名是一個指標這個我知道,我想知道為什麼不能用二級指標指向二維數組)

  

解析:首先數組和指標的概念你沒分清楚,數組的本質你沒搞清楚。這是導致問題出現的根源。

      int x[5]; 這個定義裡面,我們說定義了一個數組x,此數組有5個數組元素,元素的類型為int類型。

      首先要問的是,x到底為什麼東西?x是數組名,x代表了數組第一個元素的首地址。沒錯,x確實是數組的名字,x的值也確實是第一個數組元素的地址值。

      注意這裡我們說x代表的值與數組第一個元素的地址值相等,但類型不一樣

      那麼數組x的類型到底是什麼呢? 有人說就是int * 類型。有如下語句可以做證:

                         int *p=x; //這句話是正確的。

      數組x的類型真是int *嗎?我們說不是,因為下面的語句是不正確的:

                         int a=10; x=&a; // int *類型的變數時可以接受值的。

      所以x不是int*  那麼我們可以猜測x的類型是不是 int *const呢?也就是說x是一個地址值不可以改變的指標。這句話貌似有點正確。但是請大家看看下面的例子:

                         int x[5]={0}; int a=sizeof(x); // a的值到底是多少?

     實際上這裡a的值是5*4=20 這裡是整個數組佔用的位元組數。 我們不是說x的類型是int * const類型的嗎,也就是x應該是一個指標類型,應該是4個位元組的啊,為什麼sizeof出來時整個數組佔用的位元組數呢?例如  sizeof(int *)這個的結果就是4。所以有此可以看出,x的類型並不是int*,也不是int * const。  i

       int x[5];中的x到底是什麼呢,我們說x是數組,此數組有5個元素,並且每個元素都是int類型。 我們有一個識別資料類型的規律例如: 

       int x; //x類型為int

       int *x;//x類型為int *

       int **x;//x類型為int **

       int (*x)[10];//x類型為int(*)[10]實際上是指向數組的指標

       int (*x)(int ,int);//x的類型為int(*)(int,int)實際上是指向函數的指標 

    由此可以看出,一個符號是什麼資料類型,我們只要在其定義的運算式中去掉符號本身剩下的就是符號的類型了。

    照此推斷,int x[5];中x的類型應該是 int [5]這個類型,可以看出此類型並不是int *類型。 

    那麼int x[5];中的x可以這樣賦值: int *p=x; 為什麼呢?只能說這裡面將x的類型隱式轉換為了int *類型。所以這裡是可以賦值的,因為進行了類型轉換。

   再請看下面的例子: 

         void function(int x[5])

         {  

             cout<<sizeof(x)<<endl; //這裡輸出4

          }  為什麼會輸出4,而不是4*5呢,可以看出上面的函數形參實際上類型是int*,並不是數群組類型,

       所以我們在定義函數的時候,下面的都是與上面等價的: 

       void function(int x[])//元素個數是多少可以省略 {   cout<<sizeof(x)<<endl; //這裡輸出4 }

       void function(int *x) //直接寫成指標變數也沒錯 {   cout<<sizeof(x)<<endl; //這裡輸出4 } 

  

   那麼我們看一個類似的問題:

          int x[5]; int **p=&x; //為什麼會報錯? 因為類型不符。 

         p的類型是int **,而&x的類型卻不是int **。 &x的類型實際上是int(*)[5],因為取的是x的地址,也就是說這個地址是數組的地址,並不是指向數組第一個元素的指標的指標(也就是二維指標),而是整個數組的地址。

         所以我們可以改成下面的: int (*p)[5]=&x;//這就對了。

 

二,指向數組的指標,和指向數組元素的指標有什麼不同? 

    例如int *p;我們要注意的是,p的類型是int*,p佔用的空間4個位元組,p指向的資料類型是int。P指向的資料類型佔用4個位元組。

    所以對於指標變數,我們要明白指標變數本身是佔用空間的,本身是有類型的,其次指標變數所指向的空間是有類型的,是有空間的。 

    那麼int *p; char *p1; 對於指標變數來說p,p1裡面都放的是地址值,說白了就是一個數值,他們都佔用4個位元組的空間,但是他們的類型不一樣,p裡面的地址指向的是int類型的資料,p1指向的是char類型的資料,這主要體現在p++與p1++中他們在記憶體中移動的位元組數是不一樣的,我們假設int佔4個位元組,char佔1個位元組。那麼對於p來說向前移動了4個位元組,p1來說移動了一個位元組。這就是他們的類型不同,導致運算過程中的不同。
int x[5];

     int (*p3)[5]; 此時p3指向數組x,那麼p3++實際上向前移動了多少呢,可以算出移動了4*5個位元組。也就是p3指向的是一個數組,是整個數組,所以p3移動的時候是將一個數組當做一個整體來看待的。所以向前移動了一整個數組的距離。  再看你的問題之前,我們來看一個類似的問題: 

     int a[2][3]; int  **p=&a; //這裡我用&a來賦值行不行呢。是不行的。  這裡為什麼是錯誤的,原因就是因為&a的類型不是int**類型。所以類型不相容,導致不能賦值,同時這兩種類型是不可以相互轉換的。那麼&a到底是一個什麼樣的類型呢。 我們說&a取的是整個數組的地址,那麼&a自然就是指向整個數組的指標了。

     int (*p)[2][3]=&a; 此時這樣賦值才是正確的。如果我們要用a直接賦值,那該定義一個什麼樣的變數來接受它呢,首先要明白,數組名代表的地址類型是指向數組的第一個元素的指標,

    例如:  int a[10]; int *p=a; 實際上這裡與 int *p=&a[0];是等價的。因為指向a[0]的指標類型就是int*類型。  那麼&a的是取數組的地址,其類型是指向數組的指標,而不是指向數組第一個元素的指標,整個是要區別的,他們的類型就不一樣。 int(*p)[10]=&a; 

     所以說這裡的a和&a絕對不是同一個東西,雖然本質上他們的地址值是一樣的,但是他們的類型不一樣。就決定他們代表不同的意義。 

     那麼剛剛說了對於下面的例子:

            int a[2][3];

            int (*p)[2][3]=&a;

     我們可以定義這樣的一個變數p來接受&a的值。 

     那麼我們要接受a應該定義一個什麼樣的變數呢。a[2][3]是一個二維數組,可以看成是這樣的a是一個數組,具有兩個元素,分別為a[0],a[1]其中這兩個元素的值a[0],a[1]他們的值又是一個具有3個元素的數組。此時我們可以將a[0],a[1]看成是數組名,那麼a[0][0]就是數組a[0]的第0個元素了。對應關係如下: a[0] ---->  a[0][0],a[0][1],a[0][2] a[1]
---->  a[1][0],a[1][1],a[1][2]  那麼a到底是什麼,其實a數組有兩個元素,a[0],a[1],那麼a的值自然就是其第一個元素的地址了,也就是&a[0]了。這是一個什麼類型?  我們知道如果我們將a[0]看成一個整體,例如我們用A來代替a[0],那麼A[0],A[1]就相當於a[0][0],a[0][1] 。 此時A就是一個int類型的數組,&A,的類型實際上就是 int(*p)[3]這個類型。  所以下面的代碼也是正確的:   

      int a[2][3];  int(*p)[3]=a; //所以對於你的問題,可以這樣子

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.