Tại sao mọi người sử dụng __ (dấu gạch dưới kép) quá nhiều trong C ++


93

Tôi đã xem qua một số mã C ++ mã nguồn mở và nhận thấy rất nhiều điểm dưới gấp đôi nơi được sử dụng trong mã, chủ yếu ở đầu các tên biến.

return __CYGWIN__;

Chỉ tự hỏi là có lý do cho điều này, hay chỉ là do một số người viết mã kiểu? Tôi sẽ nghĩ rằng tôi làm cho nó khó đọc.


2
Tại sao khó đọc? Nó được thiết kế chủ yếu như một đồ thị mê sảng, giống như dấu ngoặc kép. Như tôi nhớ lại, nó chủ yếu được sử dụng cho các hằng số nội trang.
Matthew Scharley 22/10/08

1
Không, nó không phải là dấu phân cách. Dấu gạch dưới được sử dụng để phân biệt tên dành riêng cho việc triển khai với tên mà mã nguồn của người dùng có thể sử dụng. Người dùng có thể làm #define FOO 1nhưng họ không được làm #define __FOO__ 1và do đó việc triển khai được miễn phí sử dụng tên __FOO__cho các macro, biến, hàm của chính nó, v.v.
Jonathan Wakely

Tôi nghĩ Matthew muốn nói nó là một sự mê sảng về mặt phong cách / trực quan, không phải về mặt chức năng. Đó là một giả thuyết thú vị, nhưng không chính xác với những gì tôi đã đọc trước đó và câu trả lời của Jonathan.
JMI MADISON

Câu trả lời:


127

Từ Lập trình trong C ++, Quy tắc và Khuyến nghị :

Việc sử dụng hai dấu gạch dưới (`__ ') trong số nhận dạng được dành riêng cho việc sử dụng nội bộ của trình biên dịch theo tiêu chuẩn ANSI-C.

Dấu gạch dưới (`_ ') thường được sử dụng trong tên của các hàm thư viện (chẳng hạn như" _main "và" _exit "). Để tránh va chạm, không bắt đầu số nhận dạng bằng dấu gạch dưới.


1
Hướng dẫn đó có vẻ như nó đã được viết trước khi namespaceđược giới thiệu.
cz

nó cũng từ đại học hoàng gia london không phải từ tiêu chuẩn C ++; nó có thể là gợi ý tốt.
stucash

1
@cz Không gian tên không liên quan. Tiêu đề hệ thống có thể xác định tên macro bắt đầu bằng dấu gạch dưới, ví dụ _main.
martinkunev

49

Trừ khi họ cảm thấy rằng họ là "một phần của việc triển khai", tức là các thư viện tiêu chuẩn, thì họ không nên làm như vậy.

Các quy tắc khá cụ thể và hơi chi tiết hơn một số quy tắc khác đã đề xuất.

Tất cả các số nhận dạng chứa dấu gạch dưới kép hoặc bắt đầu bằng dấu gạch dưới theo sau là chữ hoa được dành riêng cho việc sử dụng triển khai ở tất cả các phạm vi, tức là chúng có thể được sử dụng cho macro.

Ngoài ra, tất cả các số nhận dạng khác bắt đầu bằng dấu gạch dưới (nghĩa là không được theo sau bởi một dấu gạch dưới khác hoặc một chữ hoa) được dành riêng cho việc triển khai ở phạm vi toàn cầu. Điều này có nghĩa là bạn có thể sử dụng những mã định danh này trong không gian tên của riêng bạn hoặc trong định nghĩa lớp.

Đây là lý do tại sao Microsoft sử dụng các tên hàm có dấu gạch dưới ở đầu và tất cả đều ở dạng chữ thường cho nhiều hàm thư viện thời gian chạy cốt lõi của chúng mà không phải là một phần của tiêu chuẩn C ++. Các tên hàm này được đảm bảo không mâu thuẫn với các hàm C ++ tiêu chuẩn hoặc các hàm mã người dùng.


1
Trong C ++, tôi chỉ thấy [lex.name] và tên chung [global.names]. Bạn có thể cho tài liệu tham khảo? thanks
a.lasram

36

Theo Tiêu chuẩn C ++, các số nhận dạng bắt đầu bằng một dấu gạch dưới được dành riêng cho các thư viện. Các số nhận dạng bắt đầu bằng hai dấu gạch dưới được dành riêng cho các nhà cung cấp trình biên dịch.


18
Hơn thế nữa: các số nhận dạng có dấu gạch dưới kép ở bất kỳ đâu trong đó đều được dành riêng. 17.4.3.1.2
Steve Jessop

Trong C ++, tôi chỉ thấy [lex.name] và tên chung [global.names]. Bạn có thể cho tài liệu tham khảo? cảm ơn
a.lasram

10

Các ý kiến ​​ở trên là đúng. __Symbol__nói chung là một mã thông báo ma thuật được cung cấp bởi nhà cung cấp trình biên dịch (hoặc trình tiền xử lý) hữu ích của bạn. Có lẽ được sử dụng rộng rãi nhất trong số này là __FILE____LINE__, được mở rộng bởi bộ tiền xử lý C để chỉ ra tên tệp và số dòng hiện tại. Điều đó rất hữu ích khi bạn muốn ghi lại một số loại lỗi xác nhận chương trình, bao gồm cả vị trí văn bản của lỗi.


8

Đó là điều bạn không nên làm trong mã 'bình thường'. Điều này đảm bảo rằng các trình biên dịch và thư viện hệ thống có thể xác định các ký hiệu sẽ không xung đột với của bạn.


5

Dấu gạch dưới kép được dành riêng cho việc triển khai

Câu trả lời được bình chọn nhiều nhất trích dẫn Lập trình trong C ++: Quy tắc và Đề xuất :

"Việc sử dụng hai dấu gạch dưới (` __ ') trong số nhận dạng được dành riêng cho việc sử dụng nội bộ của trình biên dịch theo tiêu chuẩn ANSI-C. "

Tuy nhiên, sau khi đọc một vài tiêu chuẩn C ++ và C, tôi không thể tìm thấy bất kỳ đề cập nào về việc dấu gạch dưới bị hạn chế chỉ sử dụng nội bộ của trình biên dịch. Các tiêu chuẩn mang tính tổng quát hơn, dành gấp đôi điểm nhấn cho việc thực hiện .

C ++

C ++ (bản nháp làm việc hiện tại, truy cập 2019-5-26) ở trạng thái lex.name:

  • Mỗi mã định danh có chứa dấu gạch dưới kép __ hoặc bắt đầu bằng dấu gạch dưới theo sau là chữ hoa sẽ được dành riêng cho việc triển khai cho bất kỳ mục đích sử dụng nào.
  • Mỗi số nhận dạng bắt đầu bằng dấu gạch dưới được dành riêng cho việc triển khai để sử dụng làm tên trong không gian tên chung.

C

Mặc dù câu hỏi này dành riêng cho C ++, nhưng tôi đã trích dẫn các phần có liên quan từ các tiêu chuẩn C 99 và 17:

C99 mục 7.1.3

  • Tất cả các số nhận dạng bắt đầu bằng dấu gạch dưới và chữ hoa hoặc dấu gạch dưới khác luôn được dành riêng cho bất kỳ mục đích sử dụng nào.
  • Tất cả các số nhận dạng bắt đầu bằng dấu gạch dưới luôn được dành riêng để sử dụng làm số nhận dạng với phạm vi tệp trong cả không gian tên thẻ và không gian thông thường.

C17 nói điều tương tự như C99.

Việc thực hiện là gì?

Đối với C / C ++, việc triển khai đề cập đến các tài nguyên được thiết lập cần thiết để tạo ra tệp thực thi từ các tệp nguồn của người dùng. Điêu nay bao gôm:

  • bộ tiền xử lý
  • trình biên dịch
  • người liên kết
  • thư viện tiêu chuẩn

Triển khai ví dụ

Có một số triển khai C ++ khác nhau được đề cập trên Wikipedia . (không có liên kết neo, ctrl + f "thực hiện")

Đây là một ví dụ về triển khai C / C ++ của Digital Mars dành một số từ khóa cho một tính năng của chúng.


3

Ngoài các thư viện mà nhiều người khác đã phản hồi, Một số người cũng đặt tên cho các giá trị macro hoặc #define để sử dụng với bộ tiền xử lý. Điều này sẽ giúp bạn làm việc dễ dàng hơn và có thể đã cho phép xử lý các lỗi trong các trình biên dịch cũ hơn.

Giống như những người khác đã đề cập, nó giúp ngăn chặn xung đột tên và giúp phân định giữa các biến thư viện và biến của riêng bạn.

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.