c语言指针在左还是右,C语言学习之指针的右左法则
C語言所有復雜的指針聲明,都是由各種聲明嵌套構成的。如何解讀復雜指針聲明呢?右左法則是一個既著名又常用的方法。不過,右左法則其實并不是C標準里面的內容,它是從C標準的聲明規定中歸納出來的方法。C標準的聲明規則,是用來解決如何創建聲明的,而右左法則是用來解決如何辯識一個聲明的,兩者可以說是相反的。右左法則的英文原文是這樣說的:
The right-left rule: Start reading the declaration from theinnermost parentheses, go right, and
then go left. When you encounter parentheses, the direction shouldbe reversed. Once everything
in the parentheses has been parsed, jump out of it. Continue tillthe whole declaration has been
parsed.
這段英文的翻譯如下:
右左法則:首先從最里面的圓括號看起,然后往右看,再往左看。每當遇到圓括號時,就應該掉轉閱讀方向。
一旦解析完圓括號里面所有的東西,就跳出圓括號。重復這個過程直到整個聲明解析完畢。
而我要對這個法則進行一個小小的修正,應該是從未定義的標識符開始閱讀,而不是從括號讀起,之所以
是未定義的標識符,是因為一個聲明里面可能有多個標識符,但未定義的標識符只會有一個。
現在通過一些例子來討論右左法則的應用,先從最簡單的開始,逐步加深:
int (*func)(int *p);
sizeof( func ) = 4, 它是一個函數指針,在32位系統中一個指針占4字節。
首先找到那個未定義的標識符,就是func,它的外面有一對圓括號,而且左邊是一個*號,這說明func是一個指
針,然后跳出這個圓括號,先看右邊,也是一個圓括號,這說明(*func)是一個函數,而func是一個指向這類
函數的指針,就是一個函數指針,這類函數具有int*類型的形參,返回值 類型是 int。
int (*func)( int *p, int (*f)(int*) );
sizeof( func ) = 4
func被一對括號包含,且左邊有一個*號,說明func是一個指針,跳出括號,右邊也有個括號,那么func是一
個指向函數的指針,這類函數具有int *和int (*)(int*)這樣的形參,返回值為int類型。再來看一看func的形
參int (*f)(int*),類似前面的解釋,f也是一個函數指針,指向的函數具有int*類型的形參,返回值為int。
int (*func[5])(int *p);
sizeof( func ) = 20??它是一個數組,有五個元素,每個元素都是指針,所以總共占了 5x4=20 B的空間。
這里有點復雜,用typedef分解看的比較清楚:
typedef int f(int *p);??這是一個函數;
typedef f???*pf;??????????這是函數 指針;
typedef pf??apf[5];????函數指針 類型的 數組;
也就是 它是一個 含有 五個 函數指針 元素 的數組
func 右邊是一個[]運算符,說明func是一個具有5個元素的數組,func的左邊有一個*,說明func的元素是指針
,要注意這里的*不是修飾func的, 而是修飾func[5]的,原因是[]運算符優先級比*高,func先跟[]結合,因
此*修飾的是func[5]。跳出這個括號,看右邊,也是一對圓括號,說明func數組的元素是函數類型的指針,它
所指向的函數具有int*類型的形參,返回值類型為int。
int ( * (*func)[5] )(int *p);
sizeof( func ) = 4 它是指針,所以只占四個字節
typedef int f(int *p);??這是一個函數;
typedef f???*pf;??????????這是函數 指針;
typedef pf??apf[5];????這是一個函數指針 數組
typedef apf*papf;???它是指針
func 被一個圓括號包含,左邊又有一個*,那么func是一個指針,跳出括號,右邊是一個[]運算符號,說明
func是一個指向數組的指針,現在往左看,左邊有一個*號,說明這個數組的元素是指針,再跳出括號,右邊
又有一個括號,說明這個數組的元素是指向函數的指針。總結一下,就是:func是一個指向數組的指 針,這個
數組的元素是函數指針,這些指針指向具有int*形參,返回值為int類型的函數。
int ( *(*func)(int *p) )[5];
sizeof( func ) =4?????它是指針
typedef int???a[5];?????首先它是一個數組,
typedefa?????*pa;???????它是一個指向數組的指針,指向數組的指針的表示: int??(*a)[5]
typedef pa fpa( int *p);??函數的返回值為pa,而pa是一個數組指針
typedef fpa*pfpa;???它只是個指針
func是一個函數指針,這類函數具有int*類型的形參,返回值是指向數組的指針,所指向的數組的元素是具有5
個int元素的數組。
注意:
int *( *p )[5] 和 int (* (*p) )[5]在用typedef分解時先后順序是不同的:
int *( *p )[5]
typedef?? int*p;????首先它是一個指針
typedef?? pap[5];??一個數組的5個元素類型也是指針??即指針修飾的是數組的元素
typedef??ap?? *pap; 最后它是一個指向數組的指針
int (* (*p) )[5]?typedef??int a[5];?? 首先它是一個數組
typedef??a??? *pa;?? 它是一個指向數組的指針
typedef?? pa *ppa;它是一個指向數組指針的指針
要注意有些復雜指針聲明是非法的,例如:
int func(void) [5];
func是一個返回值為具有5個int元素的數組的函數。但C語言的函數返回值不能為數組,這是因為如果允許函數
返回值為數組,那么接收這個數組的內容的東西,也必須是一個數組,但C語言的數組名是一個右值,它不能作
為左值來接收另一個數組,因此函數返回值不能為數組。
int func[5](void);
func是一個具有5個元素的數組,這個數組的元素都是函數。這也是非法的,因為數組的元素除了類型必須一樣
外,每個元素所占用的內存空間也必須相同,顯然函數是無法達到這個要求的,即使函數的類型一樣,但函數
所占用的空間通常是不相同的。
附:
1、 指針的類型
從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。這是指針
本身所具有的類型。讓我們看看例一中各個指針的類型:(1)int *ptr; //指針的類型是int *
(2)char *ptr; //指針的類型是char *
(3)int **ptr; //指針的類型是 int **
(4)int (*ptr)[3]; //指針的類型是 int(*)[3]
(5)int *(*ptr)[4]; //指針的類型是 int *(*)[4]怎么樣?找出指針的類型的方法是不是很簡單?
2、指針所指向的類型
當你通過指針來訪問指針所指向的內存區時,指針所指向的類型決定了編譯器將把那片內存區里的內容當
做什么來看待。????從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符 *去掉,剩下的就是指針所指
向的類型。例如:(1)int *ptr; //指針所指向的類型是int
(2)char *ptr; //指針所指向的的類型是char
(3)int **ptr; //指針所指向的的類型是 int *
(4)int (*ptr)[3]; //指針所指向的的類型是 int()[3]
(5)int *(*ptr)[4]; //指針所指向的的類型是 int *()[4]
在指針的算術運算中,指針所指向的類型有很大的作用。????指針的類型(即指針本身的類型)和指針所指向的類型是兩個概念。當你對C越來越熟悉時,你會發現,把
與指針攪和在一起的“類型”這個概念分成“指針的類型 ”和“指針所指向的類型”兩個概念,是精通指針的
關鍵點之一。我看了不少書,發現有些寫得差的書中,就把指針的這兩個概念攪在一起了,所以看起書來前后
矛盾,越看越糊涂。
總結
以上是生活随笔為你收集整理的c语言指针在左还是右,C语言学习之指针的右左法则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言变量作为数组长度,为什么在C中不允
- 下一篇: 表达式ya是不合法的c语言标识符,《C语