徹底攻克C語言指針

前面我們講解了指針數組、二維數組指針、函數指針等幾種較為復雜的指針,它們的定義形式分別是:

  1. int?*p1[6];?//指針數組
  2. int?*(p2[6]);?//指針數組,和上面的形式等價
  3. int?(*p3)[6];?//二維數組指針
  4. int?(*p4)(int,?int);?//函數指針

我相信大部分初學者對上面幾種形式的指針都非常迷惑,不知道該從哪里入手去理解,為什么 p1、p2 是數組,而 p3 卻是指針呢,它們僅僅是一個括號的區別。

指針是C語言中最強大最靈活的一部分,也是最難以理解的一部分,它是學習C語言的重點,沒有學會指針就無從談學會C語言。如果大家覺得上面幾種形式的指針還能勉強接受,那么下面兩個指針是不是讓人抓狂呢?

  1. char?*(*?c[10])(int?**p);
  2. int?(*(*(*pfunc)(int?*))[5])(int?*);

只要找到了竅門,再復雜的指針也是可以理解的,這節我們就來戳破這層窗戶紙!

C語言標準規定,對于一個符號的定義,編譯器總是從它的名字開始讀取,然后按照優先級順序依次解析。對,從名字開始,不是從開頭也不是從末尾,這是理解復雜指針的關鍵!

對于初學者,有幾種運算符的優先級非常容易混淆,它們的優先級從高到低依次是:

  • 定義中被括號( )括起來的那部分。
  • 后綴操作符:括號( )表示這是一個函數,方括號[ ]表示這是一個數組。
  • 前綴操作符:星號*表示“指向xxx的指針”。


學會了“絕殺招式”,接下來我們就由淺入深,逐個擊破上面的指針定義。

1)?int *p1[6];

從 p1 開始理解,它的左邊是 *,右邊是 [ ],[ ] 的優先級高于 *,所以編譯器先解析p1[6],p1 首先是一個擁有 6 個元素的數組,然后再解析int *,它用來說明數組元素的類型。從整體上講,p1 是一個擁有 6 個 int * 元素的數組,也即指針數組。

2)?int (*p3)[6];

從 p3 開始理解,( ) 的優先級最高,編譯器先解析(*p3),p3 首先是一個指針,剩下的int [6]是 p3 指向的數據的類型,它是一個擁有 6 個元素的一維數組。從整體上講,p3 是一個指向擁有 6 個 int 元素數組的指針,也即二維數組指針。

為了能夠通過指針來遍歷數組元素,在定義數組指針時需要進行降維處理,例如三維數組指針實際指向的數據類型是二維數組,二維數組指針實際指向的數據類型是一維數組,一維數組指針實際指向的是一個基本類型;在表達式中,數組名也會進行同樣的轉換(下降一維)。

3) int (*p4)(int, int);

從 p4 開始理解,( ) 的優先級最高,編譯器先解析(*p4),p4 首先是一個指針,它后邊的 ( ) 說明 p4 指向的是一個函數,括號中的int, int是參數列表,開頭的int用來說明函數的返回值類型。整體來看,p4 是一個指向原型為int func(int, int);的函數的指針。

4) char *(* c[10])(int **p);

這個定義有兩個名字,分別是 c 和 p,乍看起來 p 是指針變量的名字,不過很遺憾這是錯誤的。如果 p 是指針變量名,c[10]這種寫法就又定義了一個新的名字,這讓人匪夷所思。

以 c 作為變量的名字,先來看括號內部(綠色粗體):

char *?(* c[10])?(int **p);

[ ] 的優先級高于 *,編譯器先解析c[10],c 首先是一個數組,它前面的*表明每個數組元素都是一個指針,只是還不知道指向什么類型的數據。整體上來看,(* c[10])說明 c 是一個指針數組,只是指針指向的數據類型尚未確定。

跳出括號,根據優先級規則(() 的優先級高于 *)應該先看右邊(紅色粗體):

char *?(* c[10])?(int **p);

( )說明是一個函數,int **p是函數參數。

再看左邊(橘黃色粗體):

char *?(* c[10])?(int **p);

char *是函數的返回值類型。

從整體上看,我們可以將定義分成兩部分:

char *?(* c[10])?(int **p);

綠色粗體表明 c 是一個指針數組,紅色粗體表明指針指向的數據類型,合起來就是:c 是一個擁有 10 個元素的指針數組,每個指針指向一個原型為char *func(int **p);的函數。

5) int (*(*(*pfunc)(int *))[5])(int *);

從 pfunc 開始理解,先看括號內部(綠色粗體):

int (*(*(*pfunc)(int *))[5])(int *);

pfunc 是一個指針。

跳出括號,看它的兩邊(紅色粗體):

int (*(*(*pfunc)(int *))[5])(int *);

根據優先級規則應該先看右邊的(int *),它表明這是一個函數,int *是參數列表。再看左邊的*,它表明函數的返回值是一個指針,只是指針指向的數據類型尚未確定。

將上面的兩部分合成一個整體,如下面的藍色粗體所示,它表明 pfunc 是一個指向函數的指針,現在函數的參數列表確定了,也知道返回值是一個指針了(只是不知道它指向什么類型的數據)。

int (*?(*(*pfunc)(int *))?[5])(int *);

藍色粗體以外的部分,就用來說明函數返回什么類型的指針。

我們接著分析,再向外跳一層括號(紅色粗體):

int (*?(*(*pfunc)(int *))?[5])(int *);

[ ] 的優先級高于 *,先看右邊,[5] 表示這是一個數組,再看左邊,* 表示數組的每個元素都是指針。也就是說,* [5] 是一個指針數組,函數返回的指針就指向這樣一個數組。

那么,指針數組中的指針又指向什么類型的數據呢?再向外跳一層括號(橘黃色粗體):

int?(*?(*(*pfunc)(int *))?[5])?(int *);

先看橘黃色部分的右邊,它是一個函數,再看左邊,它是函數的返回值類型。也就是說,指針數組中的指針指向原型為int func(int *);的函數。

將上面的三部分合起來就是:pfunc 是一個函數指針(藍色部分),該函數的返回值是一個指針,它指向一個指針數組(紅色部分),指針數組中的指針指向原型為int func(int *);的函數(橘黃色部分)。

轉載于:https://www.cnblogs.com/ZYDZ/p/9496080.html

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

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

相關文章

流水線上的思考——異步程序開發模型(2)

上一期我們講了一個簡單的流水線處理流程,正如我們在上期最后所說那樣,這個簡單的流水線處理流程對于后續有慢設備操作的業務來說,性能有可能偏低。今天我們來討論一下如何提高性能的方法。首先讓我們來大致區分一下一般業務的處理方式。目前…

java ReentrantLock 鎖相關筆記

為什么80%的碼農都做不了架構師?>>> ReentrantLock重入鎖簡單理解就是對同一個線程而言,它可以重復的獲取鎖。例如這個線程可以連續獲取兩次鎖,但是釋放鎖的次數也一定要是兩次 Lock locknew ReentrantLock(true);//公平鎖 Lock …

計算機啟動程序bios_如何構建自己的計算機,第三部分:準備BIOS

計算機啟動程序biosSo you’ve carefully picked out some parts and built a computer, but it doesn’t really do anything…yet. Before we hop into installing your operating system, we need to take a quick look at the BIOS and prepare it for our operating syste…

PLSQL 之類型、變量和結構

1、類型 在《.Net程序員學用Oracle系列(5):三大數據類型》一文中詳細地講述了 Oracle 的基本數據類型,文中還提到,除基本數據類型之外,Oracle 還在語法上支持一些非固有數值類型。 事實上,Oracle 在語法上支持的數據類…

kindle圖書免費下載_如何在Kindle上免費簽出圖書館書籍

kindle圖書免費下載Tired of paying so much for ebooks? Most libraries these days let you check out eBooks, for free, just like regular books. 厭倦了為電子書支付這么多錢? 如今,大多數圖書館都讓您免費閱讀電子書,就像普通書籍一樣…

第五章 了解你的用戶

第五章 了解你的用戶邏輯人的爭議:要學會把軟件開發簡單易用象牙塔式的開發:開發團隊常年閉封在“高塔”之中,一門心思的做著魔法一般的軟件。這些開發者根本就不知道用戶會怎么樣的使用他們所做的軟件。我們應該避免這種象牙塔式的開發&…

總結之:CentOS 6.4系統裁減詳解及裝載網卡步驟

前言 隨著接觸Linux的慢慢深入、對Linux也有了一個基本認識了吧,慢慢的接觸系統內核、系統配置文件、在了解Linux的系統啟動流程后,現在來總結一下一個簡單的Linux系統的裁減方法和步驟,一個只有內核文件和幾個簡單的命令的小Linux系統&am…

android 設備占用_如何查看正在占用Android設備的空間

android 設備占用When you picked up your shiny new Android device, you probably thought “yeah, this has plenty of storage. I’ll never fill it up!” But here you are, some number of months later with a full phone and no clue why. No worries: here’s how yo…

最近沉迷生意經

高度戰略搶占顧客心智 速度戰略 . 規模不夠就談發展速度,避開自己的劣勢; . 發展速度快說明產品好,受歡迎度高; 錢是工具,從錢上解脫 . 不能被錢所困 . 放下錢,才能瀟灑地使用錢 第一時間搶占顧客心智 . 核心點就是搶占…

mysql密碼正確卻提示錯誤, 不輸入密碼反而能登錄

今天部署阿里云服務器, 發現之前可以連接的mysql服務器突然連接不上了, 密碼我確認是正確的,但登錄時就是顯示密碼錯誤, 很崩潰, 差點氣得我就想重裝mysql了。 好在經過幾番苦尋找到了以下能解決我問題的資料, 成功解決了我的問題, 萬分感謝,…

域用戶權限|安裝軟件

如何讓普通的域用戶有安裝軟件的權限?現在給客戶部署了活動目錄,客戶要求 普通的域用戶也可以自己安裝軟件。不知道如何設置,希望大家幫幫忙!我告訴客戶的做法如下:不知道可行性如何? 1、在域中新建一個域賬…

c/c++ new delete初探

new delete初探 1,new有2個作用 開辟內存空間。調用構造函數。2,delete也有2個作用 釋放內存空間調用析構函數。如果用new開辟一個類的對象的數組,這個類里必須有默認(沒有參數的構造函數,或者有默認值的參數的構造函數)的構造函數…

php舊版本windows_Windows的舊版本中如何進行多任務處理?

php舊版本windowsConsidering that DOS was a single-tasking OS and the ties it had with early versions of Windows, just how did earlier versions of Windows manage to accomplish multi-tasking? Today’s SuperUser Q&A post looks at the answers to this ques…

批量提取視頻文件信息(文件大小及時長)并統計

隨著設備性能提高,視頻文件越來越大了。服務器在對外提供視頻服務時,需要承擔越來越大的存儲負擔。一般提供1080P的AVC編碼視頻已滿足多數觀看需求。(1小時視頻大約1.3G)此文要解決的就是關于已有大量高清視頻(1小時超…

列出所有K個元素的子集-----2013年1月26日

問題描述:列出一個集合的元素個數為k的所有子集。思路:在字典順序列出所有子集的基礎上判斷元素個數就可以了&#xff0c;比較簡單。代碼如下:1 #include <stdio.h>2 #define MAX 10003 4 int main()5 {6 int n5;7 int set[MAX]{1};8 int index0;9 int …

docker swarm的應用----docker集群的構建

一、docker安裝 這里我們安裝docker-ce 的18.03版本 yum -y remove docker 刪除原有版本 #安裝依賴包 [rootDocker ~]# yum -y install yum-utils device-mapper-persistent-data lvm2 #添加docker的CE版本的yum源配置文件 [rootDocker ~]# curl https://download.docker…

微信小程序 fire_如何在Fire TV和Fire TV Stick上側面加載應用程序

微信小程序 fireAmazon’s Fire TV and Fire TV stick technically runs Android…but you wouldn’t know it from looking. Amazon has a wall of content for its set-top box, and doesn’t want Google (with its own competing platform) to crash the party. But even t…

PS 技巧

1. 鋼筆的使用&#xff1a; 扣完一圈以后&#xff0c;按Ctrl回車鍵&#xff0c;會出現螞蟻線&#xff0c;然后按CtrlJ 是復制扣出來的圖層&#xff0c;右下角的框里會出現一個新圖層&#xff0c;注意每個圖層前邊有一個小框&#xff0c;點一下是出現眼睛就可以顯示該圖層在中央…

Ibatis - Open quote is expected for attribute {1} associated with an element type '

昨天晚上提交的代碼&#xff0c;今天運行起來&#xff0c;始終報錯&#xff1a; Open quote is expected for attribute "{1}" associated with an element type id,查了半天&#xff0c;覺得很奇怪。 回滾到昨天的代碼&#xff0c;運行正常。經過compare代碼&#…

Linux系統運維之路

九月份開始&#xff0c;半年內搞定運維&#xff0c;博客會慢慢的更新&#xff0c;vim編輯器&#xff0c;Nginx配置文件優化 運維基礎 運維基礎-Linux發展史、安裝、基本操作 運維基礎-用戶和組管理 運維基礎-文件權限管理 運維基礎-進程管理 運維基礎-IO 管道 運維基礎-查找壓…