Tại sao C sử dụng dấu hoa thị cho con trỏ? [đóng cửa]


21

Tôi mới tìm hiểu về C.

Tôi thấy thật kỳ lạ khi những người sáng tạo đã chọn dấu hoa thị ( *) làm biểu tượng cho con trỏ hơn là một biểu tượng thực sự trông giống như một con trỏ ( ->).

Xem xét làm thế nào khó hiểu hội nghị và con trỏ chức năng có thể, có một lý do lịch sử, hoặc thậm chí thực tế, để sử dụng dấu hoa thị?


10
Lưu ý rằng ->đang được sử dụng trong ngôn ngữ C như một toán tử quy ước - khi truy cập các trường trong một cấu trúc : struct_pointer->field, viết tắt của (*struct_pointer).field.
amon

@amon: Nó chỉ áp dụng cho hội structsnghị, điều này có vẻ kỳ lạ đối với tôi. Đó là một biểu tượng con trỏ, phải không? Tại sao không ( <-) cho hội nghị? Tôi thực sự là người duy nhất nghĩ theo cách này?
Noob Saibot

1
Đưa ra hai câu trả lời xuất sắc trong câu hỏi này, bao gồm một câu trả lời trực tiếp từ nhà thiết kế ngôn ngữ, thật khó để biện minh cho sự gần gũi là "dựa trên quan điểm". Do đó tôi đã được đề cử để mở lại.
Jules

Phong cách IMHO Pascal là tốt hơn. ^được sử dụng và có thể được coi là một mũi tên xoay và đọc là "trỏ đến", cùng nghĩa với ->nhưng ngắn hơn. ^integercó nghĩa là "con trỏ tới số nguyên" để khai báo kiểu và var^có nghĩa là "bộ nhớ vartrỏ đến" cho hội nghị. Vị trí ký hiệu hợp lý hơn C khi đọc từ trái sang phải, luôn đặt sau loại và trước tên biến. Pascal cũng sử dụng @để lấy địa chỉ, tốt hơn là &@var"địa chỉ mà var được đặt"
phuclv

Câu trả lời:


59

Tại sao C sử dụng dấu hoa thị cho con trỏ?

Đơn giản - vì B đã làm.

Vì bộ nhớ là một mảng tuyến tính, nên có thể hiểu giá trị trong một ô là một chỉ mục trong mảng này và BCPL cung cấp một toán tử cho mục đích này. Trong ngôn ngữ gốc, nó được đánh vần rvvà sau đó !, trong khi B sử dụng unary *. Do đó, nếu plà một ô chứa chỉ mục của (hoặc địa chỉ của) hoặc con trỏ tới) một ô khác, *pđề cập đến nội dung của ô được trỏ, là giá trị trong biểu thức hoặc là mục tiêu của phép gán.

Từ sự phát triển của ngôn ngữ C

Đó là nó. Tại thời điểm này, câu hỏi không thú vị bằng "tại sao python 3 sử dụng .để gọi một phương thức? Tại sao không ->?" Chà ... bởi vì Python 2 sử dụng .để gọi một phương thức.

Hiếm khi một ngôn ngữ tồn tại từ không có gì. Nó có ảnh hưởng và dựa trên một cái gì đó đến trước.


Vậy, tại sao B không sử dụng !để hủy đăng ký một con trỏ như BCPL tiền nhiệm của nó đã làm?

Vâng, BCPL là một chút dài dòng. Thay vì &&hoặc ||BCPL được sử dụng logandlogor. Điều này là do hầu hết các bàn phím không có hoặc phím và không bằng nhau thực sự là từ NEQV(xem Hướng dẫn tham khảo BCPL ).

B dường như đã được truyền cảm hứng một phần để thắt chặt cú pháp hơn là có các từ dài cho tất cả các toán tử logic này mà các lập trình viên đã làm khá thường xuyên. Và do đó, !đối với sự tham gia đã trở thành *như vậy !có thể được sử dụng cho phủ định logic. Lưu ý rằng có một sự khác biệt giữa toán tử đơn nguyên *và toán tử nhị phân *(phép nhân).


Vâng, những gì về các lựa chọn khác , như thế ->nào?

Đã ->được thực hiện cho đường cú pháp xung quanh derefrences lĩnh vực struct_pointer->fieldđó là(*struct_pointer).field

Các tùy chọn khác như <-có thể tạo phân tích mơ hồ. Ví dụ:

 foo <- bar

Có phải là để được đọc là:

(foo) <- (bar)

hoặc là

(foo) < (-bar)

Tạo một toán tử đơn nguyên bao gồm một toán tử nhị phân và một toán tử đơn nguyên khác rất có thể có vấn đề vì toán tử đơn nguyên thứ hai có thể là tiền tố cho một biểu thức khác.

Hơn nữa, điều quan trọng nữa là cố gắng giữ cho mọi thứ được gõ thường xuyên đến mức tối thiểu. Tôi ghét phải viết:

int main(int argc, char->-> argv, char->-> envp)

Điều này cũng trở nên khó đọc.

Các nhân vật khác có thể đã có thể ( @không được sử dụng cho đến khi Mục tiêu C chiếm đoạt nó ). Mặc dù một lần nữa, điều này đi vào cốt lõi của 'C sử dụng *vì B đã làm'. Tại sao B không sử dụng @? Chà, B đã không sử dụng tất cả các nhân vật. Không có bppchương trình (so sánh cpp ) và các ký tự khác có sẵn trong B (chẳng hạn như #sau này được sử dụng bởi cpp).

Nếu tôi có thể đoán được lý do tại sao - đó là vì các phím ở đâu. Từ một hướng dẫn trên B :

Để tạo điều kiện cho việc thao tác địa chỉ khi có vẻ được khuyến khích, B cung cấp hai toán tử địa chỉ đơn nhất *&. &là toán tử địa chỉ, vì vậy &xlà địa chỉ của x, giả sử nó có một. *là toán tử gián tiếp; *xcó nghĩa là "sử dụng nội dung của x làm địa chỉ."

Lưu ý rằng đó &là shift-7 và *là shift-8. Sự gần gũi của họ với nhau có thể là một gợi ý cho lập trình viên về những gì họ làm ... nhưng đó chỉ là dự đoán. Người ta sẽ phải hỏi Ken Thompson về lý do lựa chọn đó được đưa ra.


Vì vậy, có bạn có nó. C là như vậy bởi vì B đã. B là như vậy bởi vì nó muốn thay đổi từ cách BCPL.


2
...tuyệt vời! Đây là một câu trả lời tuyệt vời, @MichaelT! Bạn đã cho tôi thấy cả lý do lịch sử và thực tế, và thậm chí cả những thứ tôi không hiểu lắm nhưng có thể xem xét. Cảm ơn bạn. +1
Noob Saibot

@NoobSaibot Việc lựa chọn nhân vật không phải là một thỏa thuận nhiều như thực tế rằng nhà điều hành là một nhà điều hành trả trước chứ không phải là nhà điều hành hoãn. Điều này đòi hỏi rất nhiều parens phụ (mặc dù -> cú pháp giúp) có thể dẫn đến các lỗi ngớ ngẩn nhưng gây phiền toái ngay cả đối với một lập trình viên C ++ có kinh nghiệm.
Trixie Wolf

1
Bạn cũng có thể đề cập rằng C đã tìm thấy một cách sử dụng cho hầu hết mọi ký tự dấu chấm câu của chữii. Không có nhiều phụ tùng. Tôi đoán @sẽ có một khả năng khác.
david.pfx

1
@ david.pfx Tôi đã mở rộng về điều đó - mặc dù không phải C đã đưa ra lựa chọn đó ... đó là B. Và, tôi đã đoán được tại sao (khoảng cách gần với bàn phím &*). B cũng không sử dụng #nên có một vài phụ tùng xung quanh sau đó ... cũng có $.

1
@ david.pfx Hướng dẫn B mà tôi tìm thấy được viết bởi BW Kernighan. Thật không may, Dennis Ritchie không còn có thể được yêu cầu (ông đã qua đời vào tháng 10 năm 11) trong khi Kernighan rõ ràng vẫn là một giáo sư trong Bộ phận CS tại Princeton. Ken Thompson (người tạo ra B) khác làm việc tại Google ... Cũng có thể có vấn đề với một số bàn phím (được biểu thị bằng chữ viết tắt của C cho những gì chúng ta nghĩ là khóa chung) cho thấy rằng không phải tất cả chúng đều có sẵn ( Tôi không chắc chắn nếu '@' là).

55

Tôi được một sinh viên hỏi nếu &*được chọn vì họ ở cạnh nhau trên bàn phím (điều mà tôi chưa bao giờ nhận thấy trước đây). Nhiều googling dẫn tôi đến tài liệu B và BCPL, và chủ đề này. Tuy nhiên, tôi không thể tìm thấy nhiều. Có vẻ như có nhiều lý do cho *B, nhưng tôi không thể tìm thấy bất cứ điều gì cho &.

Vì vậy, theo gợi ý của @ MichaelT, tôi đã hỏi Ken Thompson:

Từ: Ken Thompson <ken@google.com>

gần trên bàn phím: không.
c sao chép từ b vì vậy & và * giống nhau ở đó.
b got * từ các ngôn ngữ trước đó - một số lắp ráp,
bcpl và tôi nghĩ pl / 1.
Tôi nghĩ rằng tôi đã sử dụng và vì tên (ký hiệu)
nghe giống như "địa chỉ". b được thiết kế để chạy với
mô hình teletype 33 teletype. (Mã baud-o 5 bit)
nên việc sử dụng các ký hiệu bị hạn chế.


19
+1 để liên hệ với Ken Thompson và báo cáo lại tại đây.
stakx 15/2/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.