**p[] 和*(*p)[] 有什麼區別?

**p[] 和*(*p)[] 有什麼區別?


這是周經還是月經問題……

有個簡單的判定方法:

若有個括弧包著 //* 和標識符,則聲明的變數是左值引用/右值引用/指針,指針可能有多層。

若無這種括弧,且標識符右邊接著 [ ,則聲明的變數是數組。

表達式里不能有這兩個東西。

聲明裡,左邊需要有個指定符和可選的限定符。

下面討論 T **p[] 和 T *(*p)[] ,使用偽代碼解釋

(1) array [unknown] of ^ ^ T , ^ T 表示指向 T 的指針,下同

(2) ^ array [unknown] of ^ T

另外 (1) 在函數參數列表中被處理成 ^ ^ ^ T 。

數組聲明 - cppreference.com (2) 的形式是合法的。

個人覺得實踐中 (2) 可能沒有適用的場所, (1) 可能有。


都是錯誤的表達式

作為declarator的話,都是一輩子都用不到的形式。有些人可能會告訴你寫這種東西的人會被直接開除


可以上這個網站看看:https://cdecl.org/

char *(*p)[]

declare p as pointer to array of pointer to char

char **p[]

declare p as array of pointer to pointer to char


Type**[] 是一個數組類型,bound未知,裡面放的是Type**

Type*(*)[] 是一個指針類型,指向一個bound未知的數組,該數組裡放的是Type*

用右左法則讀一下就知道了,不用拆成好幾層,拆了反倒羅嗦不說,出了編譯錯誤以後編譯器照樣揉成整坨給你,不學會怎麼直接讀整坨的類型玩模板的時候要吃虧。

另外,數組不是指針也不相當於指針,只能decay成指針。第二個也不是語法錯誤。


前者相當於***p,後者語法錯誤


這個問題問錯了,你把它們當成表達式來問了。

如果是表達式,那麼方括弧里應該有個數字,或變數,否則你沒東西算。

那麼就應該是聲明了,你缺少了基類型。

一看就知道你是初學者,把指針聲明裡的星號,和普通算式里的間接訪問運算搞混了。

假設你的基類型是整數,用int,那麼int *p;這句話里int的意思,就是你指針里存的那個地址所對應的那個空間,是用來存整數的,不能存小數或字母等。

這個表達式是這麼看的:int * p;

不要這麼看:int *p;

int叫做基類型,int *叫做指向int型數據的指針類型——p里存的是個指針,也就是地址。

那麼int **,就是以int *為基類型的指針類型。它是指向指針的指針——它作為一個地址,所連接的存儲空間里,存的是指向int數據的地址。

所以int ** p〔〕;就是告訴計算機:給我一連串的空間,每個空間都是裝地址的,而且這些地址是指向地址的,別給我搞成指向其他類型的了……

那麼int * (*p)〔〕;想懂這句聲明,你要先明白一個概念:數組的名字,是一個指針。也就是說,數組的名字,他天然就裝著這個數組的地址(也就是它第一個元素的地址)。

比如int a〔〕;int * p;這兩句話寫出來了——那麼,我可以直接用p=a;把a的值給p。

所以int * (*p)〔〕;這句話里,(*p)相當於一個數組名,也就是地址,而這裡的*p,不是取p指向的值!而是在說:p是個指針!!!這個指針指向的指針,是這個數組的第一個元素的地址(也就是這個數組的指針)。

——再連上前面的int *——是說:有一連串的空間,每個空間里都裝的都是地址,這些地址指向的是int型數據。而p,是指針,它指向另一個指針,這個指針沒有名字,但是這個沒名字的指針,是指向這個數組的——也就是與這個數組裡的第一個元素的地址相等。

我知道你不懂,那就再舉個簡單的例子。

int a〔〕;int (*p)〔〕;這兩句話出來了,我能不能用p=a;來給p賦a值?顯然不能,因為a是個地址,p是個指向地址的地址,所以應該是p=a;來把a的地址賦給p。

或者直接寫成int (*p)〔〕=a;——這句話很有迷惑性啊!!一不留神你就把等號左邊當成個算式開始取值了——千萬時刻注意!當一個數據類型和星號共同出現時,它們的目的只有一個:告訴計算機這是指針。至於是指向啥的指針,你自己仔細。

我知道說了這麼多,可能你一個字都沒看懂。

但沒關係,這些都是純玩兒概念的,沒什麼實用價值,屬於「貴族的娛樂」~


優先順序 ()等於[]大於 *


int** p[N],二級指針的數組。

int* (*p)[N],p 指向大小為 N 的數組,且這個數組裡裝的元素是 int*。

PS, 這種聲明要先看括弧,*p代表這是一個指針。

看右邊,這個指針指向一個規模為N的數組。

最後看左邊,數組裡裝著int*。


顯然此處應使用array來避免[ ]符號。

array& *a;

array& a;

多方便。


要想弄清這些聲明的含義最行之有效的辦法是從右向左閱讀.我們看下*(*p)[],離p最近的符號就是括弧裡面的*,說明p是一個指針,數組指針具有如下形式:int (*pt)[],該指針pt指向一個數組,數組裡的元素是int,通過對比發現p指向一個數組,括弧前面的*說明數組裡面的元素是一個指針類型的。至於前面那個是二級指針,定義是這麼說的!


第一個是二級指針的數組,第二個是指向指針數組的指針


樓主可以去找一下[] 數組,()函數調用, * 解引用,這三個在一起時,假設不加括弧,他們的結合順序,弄清楚了之後,以後碰到這些都是小菜


**p[]是二級指針的數組,數組p中的每個成員都是二級指針

*(*p)[]是指向行指針的指針。

例如

*pt[2];

int *(*ptr)[2];

就可以ptr = pt;


這顯然是沒有看好C++ Primer。裡面講的很清楚。具體哪一頁忘記了。大概是在講指針或者類型別名的那部分,書中著重強調了如何去判別題主的疑惑。


推薦閱讀:

C語言和C++的基礎知識區別大嗎?
為什麼這段 c++ 代碼需要加這對括弧才正確運行,是編譯器問題嗎?

TAG:C編程語言 | C | CC | VisualC |