聲明多個指針時,為什麼實際只有第一個是指針?

聲明語句為int* p1, p2;

為何這個聲明語句創建了一個指針?一個int變數?

int*不該是一種複合類型嗎?


因為當年工程經驗不發達,那幫人感覺應當設計成:

  • int *a,讓*a的行為是int。

以便讓人更理解指針。而不設計成:

  • int* a,讓a是int的指針。

但顯然,後一種才既貼近真實情況,也符合現在人的通常期望。當年的設計純屬於圖樣圖森破。


題主,告訴你一個好記的方法,每當你要聲明一個指針時:

int *a;

你只需要看右邊,*a 一定是一個 int 類型。

int (*a)(int);

你把 (*a) 看做一個整體,就知道,(*a) 一定是一個返回 int,接受一個 int 參數的函數,所以 a 是函數指針。

int *a[5];

*a[i] 是 int,所以 a[i] 一定是 int*,所以 a 是一個數組,數組裡的每一個元素都是 int*。

int (*a)[5];

(*a)[i] 是 int,所以 (*a) 是一個 int 數組,a 是指向數組的指針。

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

(*a[i]) 是一個返回 int,接受一個 int 參數的函數,所以 a[i] 是一個函數指針,所以 a 是函數指針的數組。


建議按照SB哦不是BS老爺爺的建議,使用int* p這種語法,並且每行只聲明一個變數。指針和引用在C++里明顯在各個地方都被作為類型系統的一部分,只有這裡一股濃濃的老C味道,我們只能自己避免踩坑。

遺憾的是,為了保持C++「抓來一個C庫直接就用」的能力,C++並不能甩掉這個歷史包袱。只能忍了。


simple-declaration :

decl-specifier-seq(opt) init-declarator-list(opt) ;

// ...

decl-specifier :

type-specifier

// ...

type-specifier :

trailing-type-specifier

// ...

// ...

simple-type-specifier :

int

// ...

init-declarator-list :

init-declarator

// ...

init-declarator :

declarator initializer(opt)

declarator :

ptr-declarator

// ...

ptr-declarator :

noptr-declarator

ptr-operator ptr-declarator

ptr-operator :

* attribute-specifier-seq(opt) cv-qualifier-seq(opt)

// ...

如你所見,為了允許int (*p)[10];這種形式的語法,C/C++的聲明變得相當的變態。而為什麼是int (*p)[10];而不是int[10]* p;呢,據說是因為這種形式的聲明可以告訴你「(*p)[i]的類型是int這種東西」。。


這是 C 語言語法的 bug。

int* p1, p2 其實會被理解成 int *p1, p2,即「*p1」和「p2」都是 int,於是只有 p1 是 int 指針,p2 就是一個 int。

這種理解方法有一定道理,但很不幸跟正常人的理解方式不一樣。


這就是為什麼我寫int *a的原因


因為c的語法爛,你看pascal的做法就沒問題:

var
p1, p2, p3: ^Integer;


那個 * 只跟著 p1 走,後面的它都不管。該死的 C……


C++ primer 第五版

int是類型 *是修飾符


因為指針具有右結合性。

也給你舉個例子吧:

const char * p;

char const * p;

char * const p;

弄明白這三個就不會犯錯了吧?


請使用typedef定義一個新類型


可以靠如下思路記憶:

應該這麼讀,int (*a),也就是*a是int類型的變數。既然對a解引用後是int類型,那a就是一個指向int類型的指針。

指針里放的是地址,只要你在一番推理後發現他沒有存放地址,就得檢查一下了。


所以說推薦的寫法是int *a而不是int* a


這是個從裡到外解方程的過程

int *a, b里a經過dereference操作後得到type specifier的int,所以a是int的指針類型,這裡的*a叫declarator,而int才是公用的type specifier


你應該把*分別放在p1, p2前面。


為什麼要邀請我過來看天書?我受到了傷害


一條聲明語句由一個基本變數類型和緊隨其後的一個聲明符列表組成。(P45)

int* 不是一個基本類型,int才是,*是類型修飾符,它不過是聲明符的一部分(P51),用來修飾變數的,應該和變數名放在一起。

為了能準確解讀指針/引用的定義代碼的,讀的時候要從右向左讀(P53)。

例1:

int *a;

先看到的是a,是一個變數;

然後看到的是*,說明a是一個指針;

最後看到int,說明a是一個指向整數的變數。

例2:(這個例子參見P52-53)

int *p;

int *r = p;

先看到的時r,是一個變數;

然後看到的是,說明r是一個引用;

然後看到的是*,說明r是一個指針的引用;

最後看到的是int,說明r是一個指向int型數據的指針的引用。

詳情參考《C++ Primer 中文版》5th。


類型是類型,指針是指針。所以實際上是int *p1, p2,故一個int指針,一個int


推薦閱讀:

cpp 如何 debug memory leak?
C++中類的構造函數,成員變數是在初始化列表初始化還是在函數體中進行賦值?
cout << sizeof(vector<int>);輸出是32,為什麼?
如何用 VS 2013 打包 VC++ 程序?
設計C++函數傳參時如何決定使用指針還是引用?

TAG:C編程語言 | C | 指針 |