2012-01-20 44 views
11

聲明用C指針,有2個(編輯:3)的變體:在C中有指針聲明的約定嗎?

方案A:
int* ptr;

方案B:
int *ptr;

變型C:
int * ptr;

  • 在A中,間接運算符已被附加到該類型。
  • 在B中,間接運算符已被預置到該變量。
  • 在C中,間接運算符在類型和變量之間自由站立。

聲明指針的方式因讀取的文檔類型而異。有些作者似乎對某些變體有偏好,有些則使用幾種。

  • 我正確地認爲在不同的變體之間的功能沒有區別嗎?
  • 如果是,那麼在C中應該使用變體的約定嗎?
+3

我不知道爲什麼人們投票關閉這個。這聽起來像是一個合法的問題,但自1980年以來,我一直在黑客攻擊C。 –

+1

@PeterRowell:這種微不足道的問題的唯一問題是,可以通過谷歌或任何其他搜索在網上找到答案。發動機在幾秒鐘內。而任何有關C的書籍都必須解釋這一點。爲什麼不使用它們?不過,我沒有投票結束。 –

+1

可能重複[在C++中聲明指針時放置星號的位置是否重要?](http://stackoverflow.com/questions/5449908/does-it-matter-where-i-place-the-asterisk-when -declaring-pointers -in-c) –

回答

11

有絕對的功能

int* ptr; 

int *ptr; 

使用哪個是你沒有任何區別,有多個衝突的編碼款式可供選擇。

+1

+1。就SO而言,這是正確的答案。沒有區別,選擇是你的。 –

+0

如果你想獲得技術,使用'int * ptr;'也是等價的。只要星號介於類型名稱和變量名稱之間,空格就不重要。 – bta

+0

@DanFego:就編譯器而言,這是正確的答案。使用一種表單或其他表單是有正當理由的,SO是討論這些原因的絕佳地點。 –

6

只有當你打算在同一行聲明多個相同類型的變量時,它纔有意義。例如,如果你想多INT指針,你需要這樣做:

int *a, *b, *c; 

文體不過,當你只聲明一個變量,這是令人困惑。很多人喜歡看的類型,然後在變量名,類型應該是指向int的指針,不是int,所以他們寧願:

int* a; 
int* b; 
int* c; 

這最終取決於你是否喜歡一個之上,其他。在專業編程C的20年中,我看到大約50%的人選擇了另一種。

+0

這個(上述兩個變體)是處理尷尬的星號關聯規則的一種非常明顯的方式。我避免寫'int * a,b;','int a,* b;',和int * a,* b;'因爲它們是注意力的徵稅,而不是因爲我不知道它們每一個的含義。此外,編譯所有啓用的警告並保持代碼警告清除有助於避免不希望使用整數作爲指針,反之亦然。 –

+0

@ user1118321感謝您發佈實際解決問題的少數答案之一:在同一行中聲明多個變量。我嚴格反對將*與類型放在一起,因爲它表明開發人員實際上並不瞭解語法。 – doug65536

0

你是對的,兩者對編譯器意味着完全一樣的東西。這兩條語句都會產生一個(int *)類型的變量。

至於哪一個是正確的:蠕蟲可以! 這是一個辯論的話題。如果您爲公司或OSS工作,最好遵循一種定義的編碼風格。如果沒有一個,我通常會選擇LNT(不留痕跡)風格,以匹配這部分代碼庫中明顯使用的任何風格。

可以說,對讀者來說更容易理解。例如int* ptr;*接近int這更清楚地傳達我們正在談論的(int *)型...

1

在C,空白不除非它是需要單獨的令牌關係。你的兩個變體在語法上都是正確的。

變體1將指針操作符與類型相關聯,這足夠合理。對我來說,如果沒有爲什麼Variant 2有道理,那就足夠了。

變體2與C聲明的構造方式一致。在C語法中,指針操作符屬於聲明器(即名稱),而不是類型。在同一個聲明中聲明多個變量時,這很重要。它也有一些更深奧的案件。

因此,對我而言,變體2與C更加一致。但是任一變體都是有效的,兩種變體都是常規的。

4

它們的含義與其他人所說的相同。雖然有一個陷阱等着你。考慮以下代碼:

int* a, b; 

你可能會認爲這宣告指針int。沒有,否則。實際上aint*,但是bint。這是許多C程序員寧願將*放在變量旁邊而非類型的原因之一。當這樣寫的:

int *a, b; 

你就不太可能被誤導,什麼ab是。儘管如此,許多編碼標準堅持認爲每行只能聲明一個變量,即,

int* a; 
int b; 

如果您遵循每行規則的一個變量,那麼肯定沒有混淆的餘地。

4
T *a; 

是優選的C風格的方法來聲明一個指向T如Kernighan的& Ritchie的本書中使用約C中所用

T* a; 

優選C++式的方式來一個聲明指針T在Stroustrup關於C++的書中。

兩個符號都是等效的。

+1

呼籲權威+1 ;-) –

12

東西別人沒提的是

int *ptr; 

更符合語言的語法。

  • int *ptr;聲明,它由:
    • 一個聲明說明符int,隨後
    • 一個聲明符*ptr

(這實際上跳過一些步驟,但它橫跨得到的基本思想。)

由於聲明如下方式使用,這是什麼意思是,*ptrint類型。由此得出ptr的類型爲int*

有人可能會說,這使得它比

int* ptr; 

爲同樣的原因,

x = y+z; 

優於

x=y + z; 

當然你可以

int* ptr; 

並將其讀爲「ptrint*」類型。許多程序員都是這麼做的,相處得很好(它往往是C++的首選風格)。編譯器並不在乎你用哪種方式來做,而且任何閱讀代碼的人都不應該無法理解它。

但兩者間距讓你選擇,你需要了解什麼int *ptr;的真正含義,所以,當你看到

int *ptr, i; 

在別人的代碼(如你不可避免地會),你會立即明白ptr是一個指針和i是一個int。

如果您正在與項目中的其他程序員一起工作,那麼您應該遵循編碼標準中的任何現有約定,或者如果沒有,那麼代碼已經編寫的方式。我個人更喜歡int *ptr;int* ptr;,但使用這兩種風格的混合比使用任何一種風格要差得多。

2

C聲明基於表達式的類型,而不是對象。

如果你有一個指向名爲piint,你要訪問的整數值,它指向的,你必須取消引用指針,如:

x = *pi; 
printf("%d", *pi); 
*pi = 1 + 2; 

等。該類型的表達*pi的是int:因此,聲明應爲

int *pi; 

現在讓我們假設你有一個指針數組來char;去任何字符,則需要第一個下標到陣列,然後解除引用的結果:

c = *pc[i]; 
if (*pc[j] == 'a') {...} 

等同樣,表達*pc[i]char的類型,所以聲明讀取,

char *pc[N]; 

兩個*pi*pc[N]被稱爲說明符,並指定不被類型指定給定的附加類型的信息。 IOW,pc的數組內容和指針被指定爲聲明器的一部分,而char -ness由類型說明符給出。

至於問題,其中的風格是適當 ...

一個都不是「正確的」,但我(和許多其他的C程序員)喜歡寫T *p而不是T* p,因爲它更接近地反映了語言語法(*是聲明的一部分),它有助於在聲明多個項目時避免混淆。我見過太多人寫作的例子T* a, b;和期待b是一個指針。

對這種批評的常見反應是「每行不要聲明多個項目」。我對這種迴應的迴應是「正確編寫你的申報人,你不會有任何問題」。

有許多C++程序員,誰喜歡T* p風格之間的不同學派的,我不得不說,有少數病例(僅限於C++)那裏可以使代碼更易讀。

但是,只適用於指向T的簡單指針:當您開始處理指針數組,指向數組的指針,指向函數的指針或指向函數指針數組的指針時,範例會迅速崩潰。我的意思是,寫什麼類似

T* (*(*p)[N])(); // p is a pointer to an array of pointers to functions 
       // returning pointers to T. 

只是表示困惑的思想。儘管如此,如果你真的真的真的覺得你必須遵循T* p範式,你總是可以創造出一系列的類型定義的:

編輯

讓我們再試一次:

typedef T* TPtr;       // pointer to T 
typedef TPtr TPtrFunc();     // function returning pointer to T 
typedef TPtrFunc* TPtrFuncPtr;    // pointer to function returning 
              // pointer to T 
typedef TPtrFuncPtr TPtrFuncPtrArray[N]; // N-element array of pointer to function 
              // returning pointer to T 

TPtrFuncPtrArray* p; 

對於上帝的愛,不要這樣做。