指針數組,數組指針,指針函數,函數指針(轉)

int?? *p[4];???????? //指針數組。? 是個有4個元素的數組, 每個元素的是指向整型的指針。(數組的每個元素都是指針)
int?? (*p)[4];?????? //數組指針。 它是一個指針,指向有4個整型元素的數組。????????????????(一個指針指向有4個整型元素的數組)
int *func(void);???? //指針函數。 無參函數, 返回整型指針。           ? (函數的返回值為int*)    
int (*func)(void);?? //表示函數指針,可以指向無參, 且返回值為整型指針的函數。????? (函數的返回值為int)

右左規則:

因為C語言所有復雜的指針聲明,都是由各種聲明嵌套構成的。如何解讀復雜指針聲明呢?右左法則是一個既著名又常用的方法。不過,右左法
則其實并不是C標準里面的內容,它是從C標準的聲明規定中歸納出來的方法。C標準的聲明規則,是用來解決如何創建聲明的,而右左法則是用
來解決如何辯識一個聲明的,兩者可以說是相反的。右左法則的英文原文是這樣說的:
The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you
encounter parentheses, the direction should be reversed. Once everything in the parentheses has been
parsed, jump out of it. Continue till the whole declaration has been parsed.
這段英文的翻譯如下:
右左法則:首先從最里面的圓括號(未定義的標識符)看起,然后往右看,再往左看。每當遇到圓括號時,就應該掉轉閱讀方向。一旦解析完圓括號里面所有的東西,就跳出圓括號。重復這個過程直到整個聲明

解析完畢。
筆者要對這個法則進行一個小小的修正,應該是從未定義的標識符開始閱讀,而不是從括號讀起,之所以是未定義的標識符,是因為一個聲明里面可能有多個標識符,但未定義的標識符只會有一個。
現在通過一些例子來討論右左法則的應用,先從最簡單的開始,逐步加深:
int (*func)(int *p);
首先找到那個未定義的標識符,就是func,它的外面有一對圓括號,而且左邊是一個*號,這說明func是一個指針,然后跳出這個圓括號,先看
右邊,也是一個圓括號,這說明(*func)是一個函數,而func是一個指向這類函數的指針,就是一個函數指針,這類函數具有int*類型的形參,返回值類型是 int。

int (*func)(int *p, int (*f)(int*));
func被一對括號包含,且左邊有一個*號,說明func是一個指針,跳出括號,右邊也有個括號,那么func是一個指向函數的指針,這類函數具有int *和int (*)(int*)這樣的形參,返回值為

int類型。再來看一看func的形參int (*f)(int*),類似前面的解釋,f也是一個函數指針,指向的函數具有int*類型的形參,返回值為int。

int (*func[5])(int *p);
func右邊是一個[]運算符,說明func是一個具有5個元素的數組,func的左邊有一個*,說明func的元素是指針,要注意這里的*不是修飾 func的,而是修飾func[5]的,原因是[]運算符優先級

比*高,func先跟[]結合,因此*修飾的是func[5]。跳出這個括號,看右邊,也是一對圓括號,說明func數組的元素是函數類型的指針,它所指向的函數具有int*類型的形參,返回值類型為

int。

int (*(*func)[5])(int *p);
func被一個圓括號包含,左邊又有一個*,那么func是一個指針,跳出括號,右邊是一個[]運算符號,說明func是一個指向數組的指針,現在往左看,左邊有一個*號,說明這個數組的元素是

指針,再跳出括號,右邊又有一個括號,說明這個數組的元素是指向函數的指針。總結一下,就是:func是一個指向數組的指針,這個數組的元素是函數指針,這些指針指向具有int*形參,

返回值為int類型的函數。

int (*(*func)(int *p))[5];
func是一個函數指針,這類函數具有int*類型的形參,返回值是指向數組的指針,所指向的數組的元素是具有5個int元素的數組。
要注意有些復雜指針聲明是非法的,例如:

int func(void) [5];
func是一個返回值為具有5個int元素的數組的函數。但C語言的函數返回值不能為數組,這是因為如果允許函數返回值為數組,那么接收這個數組的內容的東西,也必須是一個數組,但C語言

的數組名是一個右值,它不能作為左值來接收另一個數組,因此函數返回值不能為數組。

int func[5](void);
func是一個具有5個元素的數組,這個數組的元素都是函數。這也是非法的,因為數組的元素除了類型必須一樣外,每個元素所占用的內存空間也必須相同,顯然函數是無法達到這個要求的,

即使函數的類型一樣,但函數所占用的空間通常是不相同的。

?

實際當中,需要聲明一個復雜指針時,如果把整個聲明寫成上面所示的形式,對程序可讀性是一大損害。應該用typedef來對聲明逐層

分解,增強可讀性,例如對于聲明:

int (*(*func)(int *p))[5];
可以這樣分解:
typedef? int (*PARA)[5];
typedef PARA (*func)(int *);
這樣就容易看得多了。
答案,同時給出用typedef的分解方法:
int (*(*func)[5][6])[7][8];
func是一個指向數組的指針,這類數組的元素是一個具有5X6個int元素的二維數組,而這個二維數組的元素又是一個二維數組。
typedef int (*PARA)[7][8];
typedef PARA (*func)[5][6];
int (*(*(*func)(int *))[5])(int *);
func是一個函數指針,這類函數的返回值是一個指向數組的指針,所指向數組的元素也是函數指針,指向的函數具有int*形參,返回值為int。
typedef int (*PARA1)(int*);
typedef PARA1 (*PARA2)[5];
typedef PARA2 (*func)(int*);
int (*(*func[7][8][9])(int*))[5];
func是一個數組,這個數組的元素是函數指針,這類函數具有int*的形參,返回值是指向數組的指針,所指向的數組的元素是具有5個int元素
的數組。
typedef int (*PARA1)[5];
typedef PARA1 (*PARA2)(int*);
typedef PARA2 func[7][8][9];

?

原帖鏈接:http://www.cnblogs.com/zhangjing0502/archive/2012/06/08/2542059.html

轉載于:https://www.cnblogs.com/chenzhefan/p/4372008.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375198.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375198.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375198.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

8086除法指令DIV,IDIV

無符號除法指令DIV(DIVision) DIV OPRD ;除數OPRD決定是8位除法還是16位除法;OPRD8位,則被除數默認在AX中,AX除以OPRD的商保存在AL中,余數保存在AH中;OPRD16位,則被除數默認在DX與AX中,結果的商保存在AX中,余數保存到DX中assume cs:code data segmentdb 2,4 data ends code se…

Hibernate 基礎配置及常用功能(二)

本章主要是描述幾種經典映射關系,順帶比較Hibernate4.x和Hibernate5.x之間的區別。 一、建立測試工程目錄 有關實體類之間的相互映射關系,Hibernate官方文檔其實描述的非常詳細,這里只提供幾種常見映射。(推薦4.3.11版本的 hibern…

三言兩語

人生中總是在選擇。每當做一件事我們都應該問問我們的內心,或多或少我們都能理解一點人生的真諦。 最近時間很充裕,也就想了好多事情。首先我想明白的第一件事就是做任何事就要勇敢的去面對、去追求。喜歡一個女孩子大概有8年了吧!這期間我們…

8086邏輯移位指令SHL和SHR

SHL邏輯左移指令 SHL OPRD M;把操作數OPRD左移M位,M為位移次數,為1或為CL(位移超過1次用CL表示) ;每移動一位右邊用0補足一位,移出的最高位進入CF(最后移出的一位寫入CF) MOV AL,00010011B ;13H 00010011B SHL AL,1 ;把AL左移1位,移出的最高位0進入CF,右邊0補足1位…

YTU 2903: A--A Repeating Characters

2903: A--A Repeating Characters 時間限制: 1 Sec 內存限制: 128 MB提交: 50 解決: 30題目描述 For this problem,you will write a program that takes a string of characters,S,and creates a new string of characters,T,with each character repeated R times.That is,…

JavaScript 模擬裝飾者模式

/*** 抽象coffee父類,其實可以不用的*/ function Coffee () {} Coffee.prototype.cost function() {throw 實現這個方法; }; /*** 黑咖啡,其實可以不用繼承的;*/ function BlackCoffee () {} // BlackCoffee.prototype new Coffee(); // Bl…

8086算術移位指令SAL和SAR

SAL算術左移指令同邏輯左移指令進行相同動作,機器指令一樣,只是為了方便記憶而提供的兩個助記符 SAR算術右移指令 SAR OPRD,M ;該指令使操作數右移M位,每移動1位左邊的符號保持不變,移出的最低位進入CF mov al,26H ;00100110B 右移1位 00010011B sar al,1 ;26H/2H13H mov a…

const 和readonly

原文:http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html 關于 const和readonly修飾符之間的區別,要牽涉到C#中兩種不同的常量類型: 靜態常量(compile-time constants) 和動態常量(runtime constants) 靜態常量是指編譯器在編譯時候會對常量進行解析,并將常量的…

Objective - C 小談:UIPickerView 和 UIDatePicker的基本使用

1.UIPickerView 1.1. UIPickerView的常見屬性 // 數據源(用來告訴UIPickerView有多少列多少行) property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;// 代理(用來告訴UIPickerView每1列的每1行顯示什么內容,監聽UIPickerView的選擇) property(nonatomic,…

8086移位指令

8086有如下3條一般移位指令 SAR OPRD,M ;算術右移 對無符號數和有符號數而言右移1位相當于原數除以2 SHR OPRD,M ;邏輯右移 對無符號數右移1位相當于原數除以2 SHL OPRD,M/SAL OPRD,M ;邏輯/算術左移(兩個助記符只有一個機器指令,進行相同的動作)左移1位相當于原數*2

ADO連接ACCESS數據庫

首先在StdAfx.h中加入 建立連接&#xff1a;(在xxApp文件中) 1 聲明變量 2 建立連接 (1) AfxOleInit 初始化 OLE 為應用程序的支持。 BOOL AFXAPI AfxOleInit( ); 返回值 非零&#xff0c;如果成功;0&#xff0c;如果初始化失敗&#xff0c;可能&#xff0c;因為安裝該 OLE 系…

MySQLdb autocommit的坑

今天寫的一個小功能&#xff0c;里面要用MySQLdb更新數據庫&#xff0c;語句如下 sql "update %s.account_operation set status1 where username%s" % (allResDBInfos[db], username)變量替換后&#xff0c;是下面的樣子 update suspects.account_operation set st…

8086段寄存器

8086有四個段寄存器CS,DS,SS,ES 任意時刻CPU執行CS:IP指向的指令,CS為代碼段寄存器(IP為指令指針寄存器) 任意時刻SS:SP指向棧的棧頂單元,SS為棧段寄存器 我們尋找數據需要知道數據在內存的位置用DS尋址 DS為數據段寄存器 ES為附加段寄存器可作為目的地址的段地址比如ES:DI…

用jquery給元素綁定事件,一些內部細節

按看段代碼&#xff1a; 1 $(.test).on(click, function() { 2 console.log(hello); 3 $(this).removeClass(test); 4 }); 就算是remove掉class test&#xff0c;照樣可以點&#xff0c;事件綁定的是這個對象。 轉載于:https://www.cnblogs.com/lqj12138/p/4384596.html

8086數據寄存器

8086CPU有四個16位數據寄存器可分成8個8位寄存器 AX(AH,AL)|BX(BH,BL)|CX(CH,CL)|DX(DH,DL) 數據寄存器主要用來保存操作數和保存運算結果等 AX 常用作累加器(accumulator)用來保存臨時數據比如MOV AX,DATA將數據段地址送入AX ;MUL BL,DIV BX用來保存乘除法的結果 BX 基(Ba…

使用搜索欄過濾collectionView(按照首字母)

1.解析json數據NSDictionary *citiesDic [CoreJSONSerialization coreJSONSerialization:"cities"];NSDictionary *infor [citiesDic objectForKey:"infor"];NSArray *listItems [infor objectForKey:"listItems"]; 2.存儲數據 for (NSDicti…

《哪來的天才?練習中的平凡與偉大》

這是一本堪稱論述所有偉大成就來源的書中最讓我覺得激動人心、非常棒的一本書。 什么成就了一個那些所謂的天才&#xff1f;刻意練習&#xff01;偉大的成就不是因為所謂天生的基因&#xff0c;也不是所謂簡單的埋頭苦干。而是需要長時間有針對性的刻意提高自己某個方面能力的艱…

8086變址和指針寄存器

SI和DI稱為變址寄存器,在字符串操作中SI作為源指針,DI作為目的指針(ES:DI<--DS:SI) ;用作存儲器指針時可用于尋址 DS:[SI],DS:[BXDI]BP和SP稱為指針寄存器,BP稱為基址針,SP為堆棧指針 ;BP也可作為存儲器指針DS:[bpsi],如果沒有段前綴那么BP最為堆棧基址[BP]尋址的是堆棧內存…

R軟件中 文本分析安裝包 Rjava 和 Rwordseg 傻瓜式安裝方法四部曲

這兩天&#xff0c;由于要做一個文本分析的內容&#xff0c;所以搜索了一天R語言中的可以做文本分析的加載包&#xff0c;但是在安裝包的過程&#xff0c;真是被虐千百遍&#xff0c;總是安裝不成功。特此專門寫一篇博文&#xff0c;把整個心塞史暢快的釋放一下。 ------------…

省賽之路第一天

今天是清明假期第一天&#xff0c;原定的到洛陽玩也成為了虛無縹緲的東東了吧&#xff0c;cb這位還有說的太對了&#xff0c;no game&#xff0c;no girlfriend&#xff0c;no holiday&#xff0c;only maching&#xff01;這都不是什么大事&#xff0c;畢竟自認為還是個肯吃苦…