2010-04-24 34 views
28

trong C++, các phương tiện sau đây "phân bổ bộ nhớ cho một con trỏ int":Loại Website tuyên bố - Pointer Asterisk Chức

int* number; 

Vì vậy, dấu hoa thị là một phần của các loại biến; không có nó, điều đó có nghĩa là "cấp phát bộ nhớ cho một int".

Sau đó, nó sẽ không có ý nghĩa hơn nếu sau đây có nghĩa là "cấp phát bộ nhớ cho hai int con trỏ"?

int* number1, number2; 
+0

bản sao có thể có của http://stackoverflow.com/questions/377164/whats-your-preferred-pointer-declaration-style-and-why –

+4

[Câu trả lời của Stroustrup] (http://www.stroustrup.com/bs_faq2 .html # khoảng trắng) cho cùng một câu hỏi. – legends2k

Trả lời

48

Stroustrup được hỏi này và ông nói (diễn giải)

  • nếu bạn suy nghĩ nhiều hơn C-ish bạn sẽ nói int * anhân viên * pE (vì vậy trong đầu của bạn, bạn đang suy nghĩ "nội dung của một là một số nguyên")
  • nếu bạn suy nghĩ nhiều hơn C++ - ish bạn sẽ nói int * anhân viên * pE (vì vậy trong đầu của bạn đó là "một là một con trỏ số nguyên")

Bạn có thể nghĩ rằng tuy nhiên bạn thích, miễn là bạn không bao giờ tuyên bố hai ponters trên cùng một dòng.

Làm việc cho tôi. Tôi là một người thuộc loại Employee* pE, nhưng tôi đã kết hôn với một loại người Employee *pE - lời khuyên của tôi sẽ không làm quá sức.

+1

xem http://www.stroustrup.com/bs_faq2.html#whitespace để tham khảo – Slava

20

Thực ra dấu hoa thị được gắn vào biến (một quy ước kế thừa từ C), vì vậy

int * number1, number2; 

tuyên bố number1 như một con trỏ đến int (tức *number1 là một int), và number2 như một int.

Khoảng cách không ảnh hưởng đến cách số number được nhập. Nó chỉ phục vụ như một dấu phân cách dấu hiệu. Tất cả những điều sau đây đều giống với trình biên dịch, vì các khoảng trống sẽ bị xóa sau khi phân tích cú pháp.

int *a; 
int*a; 
int* a; 
int * a; 
int/**a***/*/*a***/a; 

Sử dụng

int* number1, *number2; 

để tạo ra hai con trỏ, hoặc thậm chí tốt hơn, chia nó thành nhiều tờ khai để tránh nhầm lẫn.

int* number1; 
int* number2; 
+0

Cảm ơn, nhưng tôi không hỏi làm thế nào tôi nên viết nó. Tôi đang đặt câu hỏi tại sao trình biên dịch được thiết kế theo cách đó. Điều gì làm cho cú pháp này hợp lý hơn. – Feyyaz

+10

@sahs: Không có lý do chính đáng nào là cách nó ngoại trừ "nó luôn luôn theo cách này". Đây không phải là tất cả những gì hợp lý, thay vào đó là _historical_. C, từ đó chúng tôi thừa hưởng cú pháp khai báo này là 40 tuổi và cũng có nhiều phần lớn được coi là thiết kế ngôn ngữ tốt ngày nay. – sbi

3

Không,

int* number1, number2; 

Tuyên bố number1 như một con trỏ đến int, và number2 như một int. Cá nhân, tôi cũng thích gắn dấu sao để các loại, trong đó bị chính xác Gotcha bạn đưa lên trong câu hỏi này, vì vậy tôi sẽ tuyên bố hai con trỏ như sau:

int* number1; 
int* number2; 
8

Đây chỉ là một trong rất nhiều bất thường của Cú pháp khai báo của C. Công cụ sửa đổi loại * là một phần của loại, nhưng cú pháp đó thuộc về định danh được khai báo.
Điều này cũng đúng cho &[], BTW.

Xem here đối với những gì * không làm thay đổi loại.

+0

Đây không phải là một bất thường của cú pháp C. Đây là một phần của cú pháp khai báo thông thường sau khi sử dụng. Câu trả lời này dựa trên sự hiểu lầm của cú pháp C mà các khai báo trông giống như: ''. Đây không phải là cách C khai báo cú pháp hoạt động, và nếu bạn nghĩ rằng bạn sẽ bị lặp đi lặp lại nhiều lần và tìm bất thường. – Peaker

+2

@Peaker: Tôi đã học cách không thích cú pháp khai báo của C vào khoảng năm 1992. Lần đầu tiên tôi kiếm được tiền viết mã C++ (sử dụng cú pháp khai báo của C) 20 năm trước. Tuy nhiên, sự thật, theo thói quen và sử dụng thường xuyên hơn hai thập kỷ, tôi có thể hiểu (hầu hết) nó ngay lập tức, và rằng tôi yêu C++ không ngăn cản tôi công nhận cú pháp khai báo là thất bại hoàn toàn, mà chỉ có thể được miễn bởi thời cổ đại khổng lồ của nó. Bạn cũng vậy, nên học cách phân biệt giữa cái xấu mà bạn quen với việc tiếp xúc thường xuyên và cái tốt được công nhận ngay lập tức. Chỉ cần tiếp tục học! – sbi

17

Bạn đang đơn giản hoá cấu trúc khai báo C++ (mặc dù các điểm bạn tạo là hoàn toàn hợp lý). Chỉ ngay từ cái nhìn đầu tiên, có vẻ như việc khai báo C++ bao gồm tên kiểu và một chuỗi các tên thực thể được phân tách bằng dấu phẩy, nhưng trên thực tế trong khai báo C++ (cũng như trong C) thực sự bao gồm tên kiểu và trình tự của các khai báo . Thông tin loại đầy đủ cho thực thể bạn khai báo được chia giữa hai các vị trí riêng biệt và một phần của nó thực sự là một phần của người khai báo. Nó chỉ là cách nó là trong C + +. Để phản ánh tốt hơn cấu trúc thực tế của việc kê khai (theo cách nhìn của ngôn ngữ), nó có thể là một ý tưởng tốt để khai báo định dạng như

int *a, *b; 

nghĩa một cách rõ ràng nhóm * s với tên thực thể, không phải với các loại Tên. (Nhưng cuối cùng đó là vấn đề sở thích cá nhân.)

Vì lý do tại sao nó được thiết kế theo cách đó trong ngôn ngữ, khi bạn hỏi một trong các ý kiến ​​... Như bạn đã biết, các phần của cú pháp khai báo như trên mô tả các loại thực thể được tuyên bố có thể xuất hiện ở phía bên trái của tên (như *&) cũng như đứng về phía bên tay phải của nó (như ()[]) như trong

int *f(), (&g)[5], h[2][2]; 

Đối với các bit xuất hiện ở bên phải, đơn giản là không thể thực hiện theo bất kỳ cách nào khác. Họ không có lựa chọn nào khác ngoài việc được nhóm với tên thực thể, chứ không phải với tên loại. Người ta có thể hỏi thêm tại sao tờ khai nêu trên không được thực hiện trong C++ như

int *() f; 
int (&)[5] g; 
int [2][2] h; 

(tức là tất cả mọi thứ liên quan đến loại xuất hiện ở phía bên tay trái trong một nhóm nhỏ gọn) ... Vâng, câu trả lời cho câu hỏi này là chỉ là nó là cách nó là trong C + +. Cách tiếp cận được kế thừa từ C và ở đó "tuyên bố phải giống với việc sử dụng" thường được trích dẫn như là lý do cơ bản.

P.S. Một điều cần nhớ (và những gì thường được giải thích không chính xác) là các vòng loại liền kề với tên kiểu trong khai báo là một phần của loại phổ biến, không phải là một phần của người khai báo cá nhân đầu tiên.Ví dụ

int const *a, *b; 

tuyên bố const int *aconst int *b, không int *b như một số có thể mistakingly tin. Vì lý do này cá nhân tôi thích sử dụng hợp lý hơn

const int *a, *b; 

đặt hàng (mặc dù cùng một lúc tôi thích vào nhóm * với tên, không phải với loại).

+0

Có vẻ hợp lý hơn khi bạn nhóm '*', '&', '()' và '[]' với tên như mô tả về biến _that_ mặc dù chúng sửa đổi loại của nó nhưng không thay đổi kiểu của tất cả các biến khác trong cùng một dòng; các vòng loại tương tự như vậy được liên kết với tất cả các biến được khai báo trong dòng đó và do đó, hãy sử dụng dấu phẩy để chuẩn bị chúng với kiểu có vẻ chính xác. Tôi đã làm điều này mà không suy nghĩ về lý do, bây giờ tôi biết, vì vậy tôi sẽ tiếp tục gắn bó với nó, ngay cả ở nguy cơ ai đó đánh giá tôi như một lập trình viên C giả mạo như một lập trình viên C++. – legends2k

+0

Marshall Cline sử dụng mỉa mai trong việc trả lời [câu hỏi thường gặp tương tự] (http://www.parashift.com/c++-faq/void-in-param-list.html) _ (xem phần cuối) _ để lưu ý những định kiến ​​như vậy không đúng. – legends2k