C/C++ 里指針聲明為什麼通常不寫成 int* ptr 而通常寫成 int *ptr ?
int* ptr = a;
明顯要比
int *ptr = a;
更符合語意吧。前者把 int* 當成一個運算元作用在 ptr 上,聲明 ptr 是一個指針變數,儲存了變數 a 的地址。而後一種語意明顯不一致,*ptr 本來就表示 a 的值,而聲明的時候好像是把變數 a 的地址賦給指針指向的變數。此外 ptr 本來就等於 a ,所以我想按前一種的寫法不是更符合語意的一致性嗎?
-------------------------------------------補充一點,我知道在
int* var0, var1;
這種聲明下 var0 是 int 型指針,var1 是 int 類型。但是這種破壞一致性的語意難到不反人類嗎?
-------------------------------------------
再補充一點,其實寫成 int *ptr 也可已理解,就像 @馮東 和@顧笑群 回答里的解釋。但是在用數組給指針初始化的時候又可以寫成 int* ptr = ary, 既然 ary 能表示 ary[0] 的地址,那為什麼不能在用原始類型給指針初始化的時候寫成 int* ptr = a ? 這樣也更符合上面兩個答案里的意思。
希望大家不要繼 tab vs space、{ 是否換行之後,再搞多兩個派別。如果要搞,可以再加多兩種:
int *p; // 1. 很多書都這樣寫吧
int* p; // 2. 我好像近十年習慣這麼寫
int * p; // 3. 一人讓一步吧
int*p; // 4. 異類!拖出去!
.
C++ Style and Technique FAQC++之父的解釋他的個人主頁寫的東西很值得一讀。Is ``int* p;"" right or is ``int *p;"" right?
Both are "right" in the sense that both are valid C and C++ and both have exactly the same meaning. As far as the language definitions and the compilers are concerned we could just as well say ``int*p;"" or ``int * p;""
The choice between ``int* p;"" and ``int *p;"" is not about right and wrong, but about style and emphasis. C emphasized expressions; declarations were often considered little more than a necessary evil. C++, on the other hand, has a heavy emphasis on types.
A ``typical C programmer"" writes ``int *p;"" and explains it ``*p is what is the int"" emphasizing syntax, and may point to the C (and C++) declaration grammar to argue for the correctness of the style. Indeed, the * binds to the name p in the grammar.
A ``typical C++ programmer"" writes ``int* p;"" and explains it ``p is a pointer to an int"" emphasizing type. Indeed the type of p is int*. I clearly prefer that emphasis and see it as important for using the more advanced parts of C++ well.
The critical confusion comes (only) when people try to declare several pointers with a single declaration:
int* p, p1; // probable error: p1 is not an int*
Placing the * closer to the name does not make this kind of error significantly less likely.
int *p, p1; // probable error?
Declaring one name per declaration minimizes the problem - in particular when we initialize the variables. People are far less likely to write:
int* p = i;
int p1 = p; // error: int initialized by int*
And if they do, the compiler will complain.
Whenever something can be done in two ways, someone will be confused. Whenever something is a matter of taste, discussions can drag on forever. Stick to one pointer per declaration and always initialize variables and the source of confusion disappears. See The Design and Evolution of C++ for a longer discussion of the C declaration syntax.
C 語言設計的本意並不是把「int*」作為類型聲明。它的設計本意是解一個方程,
int ....讓 .... 的類型是 int。也就是 *ptr 的類型是 int。從而反推出 ptr 是 int 指針。解方程的語義,才是
int *pt, *pt2;
的寫法的由來。函數指針也是這樣,
int (*func)();最早調用是必須寫成 (*func)() 的。後來變成寫 func() 也可以了。但是本意是解方程,(*func)() 表達式是 int 類型。後來 C++ 加了 搞亂了這個規矩。但是為了對 C 兼容很多文化還是保留下來了。
我自己還是寫成 int* ptr 的。比如這個
int* a, b;你以為是int* a; int* b;但實際上是
int* a; int b;但是!
解決這個問題最好的的辦法,是絕不在一句話中定義多個變數。兩種寫法都是等價的。c語言聲明的標準是:declaration-specifiers init-declarator-list;其中declaration-specifiers是extern,static等修飾符加上char,int等基本類型,init-declarator-list是變數名加上*, [], ()等修飾符。編譯時會先解析出類型,所以對於int* var0, var1, 你看到的是(int *) (var0), (var1), 編譯器看到的是(int)(* var0), (var1)。又因為編譯過程中空白字元是被忽略的,所以不僅int* var0, var1和int *var0, var1是等價的,int * var0, var1和上面兩種寫法也是等價的。事實上,你可以添加任意個空白字元。但是,int* ptr的寫法容易導致認為int*是基本類型,從而認為int* 後面的變數都是這個類型。舉個例子:int* a, b。初學者很容易誤認為a,b都是指針,但實際上只有a是指針。
而int *ptr的寫法則不容易產生混淆。在聲明int *a, b中,*a, b都是整數型。所以a是整數指針。
這樣寫的人通常都喜歡把一大堆變數定義在一行裡面,which is不好的。
只是補充一點,這確實可能是C/C++設計考慮欠缺的地方。至於為什麼建議"*"靠後,primer上給了充分的理由,我不多說了。
其實題主所說的是合理的,記得也看到有提議說所有的類型相關的都前置,標識符都後置。比如函數指針就可以寫成`void (*)() pointerToFunction`。只是C++確實沒那麼做。不過,也可以看到,java在設計的時候就考慮到了這點,數組的定義成了`sometype[] array1, array2;`。個人覺得歷史遺留因素233。我把C語言之父的《C程序設計語言》請來了,拍了指針這節的內容:
這裡就可以看出一些端倪了。
【*】是運算符,所以它的正確使用是作用在操作數上【而不是和int類型組合】,這在第二幅圖片也有說明即【表達式*ip】。
因此,int表示的是【*ip】這個表達式的類型。從表達式【*ip】反向推出未使用*操作的ip是個地址。
私以為,比較規範的寫法就是 int *ip這種形式,全書也確實全是這種寫法。其實這個並不是必須的,但是這樣寫有一個好處:我們比較一下int *ptr, a和int* ptr, a你就會發現視覺效果上的區別了,特別是對於很多新手來說,會誤以為int*是一個跟int,bool類似的一個東西
我是int* ptr黨,我習慣把這個作為【int型指針變數ptr】來理解,這樣函數參數和返回值就是int* foo(int* a),統一的格式多好看,另外不推薦同一行定義多個變數。
這和花括弧同行還是換行的問題有什麼區別嘛。。我個人習慣int* ptr;的寫法。我也從來不會把多個變數申明寫在一行里。但是就算把多個變數申明在一行里然後發生誤用,現在的C/C++編譯器也都是會報錯的啊。
《C++ primer》(第五版)中說明了
Declarations (cppreference wiki)Overview of Declarators (msdn library)不知道你習慣看cppreference wiki還是msdn,所以都貼上了。
int * ptr;
現在無論go還是rust,都把*放前面了,所以就是C當初設計的錯誤。
int* ptr = a;
我就喜歡這樣寫啊 我一直把指針理解成為一種數據類型啊
否則的話怎麼理解typedef int* pint;
這麼糾結啊,還是 typedef 成 LPVOID、LPSTR 這樣的形式吧……
因為C語言在設計的時候比較早,很多理念還圖樣,比如認為*ptr應當行為像其所指物一樣。
因為我國法律不讓燒死異教徒
int*不是類型,int才是類型,*是操作符,這個設計邏輯我懂
但既然這樣,就不要再搞個int* p以後,decltype(p)是int*,這自相矛盾我看著很累啊更別說比如typedef int* intptr了,這不是類型?覺得int *p, *q好看的,難道不覺得這個星號在各種邏輯下總是格格不入無法統一嗎?
難道還會比這個更好看?using intptr = int*;intptr p, q;對了,用int*,或者intptr這樣的寫法還有個好處——我可以全局搜索我工程里有多少個特定類型的指針變數
所以,還是把int*當做類型吧。頂多就是不配合using或typedef時不能int* p,q
但把變數連續聲明寫在同一行,這燒死不為過吧?————————————
解釋下為何要燒死1、寫在同一行,如何初始化?變數不初始化直接用,萬一用出事誰負責?或者都寫初始化,一行代碼戳穿屏幕咯?2、別和我說多餘的初始化浪費性能——連多餘初始化都優化不掉的編譯器活該倒閉3、請問,全部寫在一行的變數,我該怎麼寫注釋?不過這樣寫的都習慣int a,b,c,d; int *p,*q,*r,*s的命名風格了,要燒死也輪不到寫注釋的來燒推薦閱讀:
※c語言b++<15是b和15比,還是b+1和15比?
※C語言中 *p++ = *p 是如何工作的?
※C/C++中++符號的運算順序是怎樣的?
※C 語言的內存管理如何比 C++ 的 RAII 靠譜?