Câu hỏi C là gì ??! ??! nhà điều hành làm gì?


Tôi thấy một dòng C trông như thế này:

!ErrorHasOccured() ??!??! HandleError();

Nó được biên dịch chính xác và dường như chạy ok. Nó có vẻ như nó đang kiểm tra nếu một lỗi đã xảy ra, và nếu nó có, nó xử lý nó. Nhưng tôi không thực sự chắc chắn những gì nó thực sự làm hoặc làm thế nào nó làm việc đó. Nó trông giống như các lập trình viên đang cố gắng thể hiện cảm xúc của họ về lỗi.

Tôi chưa bao giờ thấy ??!??! trước đó trong bất kỳ ngôn ngữ lập trình nào, và tôi không thể tìm thấy tài liệu ở bất cứ đâu. (Google không trợ giúp với các cụm từ tìm kiếm như ??!??!). Nó làm gì và mẫu mã hoạt động như thế nào?


1605
2017-10-19 16:56


gốc


thể hiện cảm xúc của bạn theo một cách khác, không sử dụng các dấu vết, viết mã có thể được hiểu bởi con người - David Heffernan
@ PeterOlson, bạn mong đợi như thế nào !ErrorHasOccurred() ??!???! HandleError(); để biên dịch? Đó là ??!  ???  !. Chứng minh quan điểm? - Michael Kjörling
Tôi đề nghị bạn đọc lên trên mã sạch. ErrorHasOccured () nên được cấu trúc lại thành ErrorHasNotOccured () do đó làm sạch dấu chấm than ... ai có thời gian để hiểu tất cả các toán tử này ??! - KadekM
Tôi thích hơn ErrorHasOccured() && HandleError() riêng tôi. Đó cũng là cách Lua làm điều đó. - Hugo Zink
@KadekM, di chuyển các phủ định vào tên chức năng không làm cho mã sạch, thay vì ngược lại. - marcelm


Các câu trả lời:


??! là một trigraph dịch sang |. Vì vậy, nó nói:

!ErrorHasOccured() || HandleError();

trong đó, do mạch ngắn, tương đương với:

if (ErrorHasOccured())
    HandleError();

Guru của Tuần (giao dịch với C ++ nhưng có liên quan ở đây), nơi tôi chọn cái này.

Có thể xuất xứ của trigraphs hoặc như @ DwB chỉ ra trong các ý kiến ​​thì nhiều khả năng là do EBCDIC gặp khó khăn (một lần nữa). Điều này thảo luận về hội đồng nhà phát triển IBM dường như hỗ trợ lý thuyết đó.

Từ ISO / IEC 9899: 1999 §5.2.1.1, chú thích cuối trang 12 (h / t @ Random832):

Trigraph sequence cho phép đầu vào của các ký tự không được định nghĩa trong Invariant Code Set as   được mô tả trong ISO / IEC 646, là tập hợp con của bộ mã ASCII bảy bit.


1320
2017-10-19 16:58



Trigraphs ban đầu là cần thiết trong trường hợp bạn bàn phím không có ví dụ như một '|' ký hiệu. Đây là một trong hai lập trình viên cố ý gây phiền toái hoặc một số biên tập kỳ lạ 'tính năng' - Martin Beckett
Yeah, nó tương đương với if (ErrorHasOccured()) HandleError(). Rất may, bạn thường chỉ gặp phải thành ngữ này trong mã perl. - user786653
Nó không nhất thiết là EBCDIC - tập hợp các ký tự yêu cầu các dấu phẩy gần như khớp chính xác với các ký tự không phải là bất biến trong ISO-646 (tức là các chuẩn ascii cũ của quốc gia). - Random832
Một lựa chọn hoàn toàn có thể đọc được sẽ là ErrorHasOccurred() && HandleError(); Đó là, nếu bạn đang sử dụng để shell scripting. :) - Yam Marcovic
Đọc nó dưới dạng "Không có ErrorHasOcurred hoặc bạn phải HandleError", @SparkyRobinson. - Omar Antolín-Camarena


Vâng, tại sao điều này tồn tại nói chung có lẽ khác với lý do tại sao nó tồn tại trong ví dụ của bạn.

Tất cả bắt đầu từ nửa thế kỷ trước với việc sử dụng lại các thiết bị đầu cuối truyền thông cứng như giao diện người dùng máy tính. Trong thời kỳ ban đầu của Unix và C, đó là ASR-33 Teletype.

Thiết bị này chậm (10 cps) và ồn ào và xấu xí và quan điểm của nó về bộ ký tự ASCII kết thúc ở 0x5f, vì vậy nó có (nhìn kỹ vào pic) không có phím nào:

{ | } ~ 

Trigraphs được xác định để khắc phục một vấn đề cụ thể. Ý tưởng là các chương trình C có thể sử dụng tập hợp con ASCII tìm thấy trên ASR-33 và trong các môi trường khác thiếu các giá trị ASCII cao.

Ví dụ của bạn thực sự là hai ??!, mỗi nghĩa |, kết quả là ||.

Tuy nhiên, những người viết mã C gần như theo định nghĩa có thiết bị hiện đại,1 vì vậy tôi đoán là: ai đó khoe khoang hoặc vui vẻ, để lại một loại trứng Phục sinh trong mã để bạn tìm.

Nó chắc chắn làm việc, nó dẫn đến một câu hỏi SO phổ biến cực kỳ phổ biến.

ASR-33 Teletype

ASR-33 Teletype


1. Đối với vấn đề đó, các trigraphs được phát minh bởi ủy ban ANSI, lần đầu tiên gặp sau C trở thành một thành công chạy trốn, vì vậy không có mã C hoặc mã lập trình C gốc nào đã sử dụng chúng.


355
2017-10-19 21:09



Nó không phải là trường hợp duy nhất của các ký tự bị thiếu, trong bàn phím và bộ ký tự. Commodore 64 có thể quen thuộc hơn với rất nhiều người trong độ tuổi từ 30 trở lên - nhân vật được hiển thị đặt cả hai dấu ngoặc (và có lẽ cả thanh và dấu ngã) - trong trường hợp này vì "ASCII" không phải là ASCII . Trong ECMA-6 (hầu như luôn được gọi là ASCII, nhưng không phải là US-ASCII), có 18 mã cụ thể theo từng vùng, nhưng tôi không biết chúng là mã nào. Một điều tôi có thể nói chắc chắn - trong "ASCII" của Anh, #đã được thay thế bằng £. Ở các khu vực khác, có thể "ASCII" không có niềng răng, v.v. - Steve314
Bộ ký tự ATASCII tương tự cho các máy tính Atari 8 bit cũng thiếu {} cũng như ~ và `. - dan04
Xem những cái này  hai Bài viết trên Wikipedia. Tôi chỉ đủ tuổi để nhớ lại thời đại của các bộ ký tự quốc gia 7 bit (mặc dù tôi chắc chắn rằng họ vẫn còn nán lại ở một số góc không rõ ràng), và cuốn sách đầu tiên tôi học được từ C thấy cần thiết để cảnh báo về khả năng của if (x || y) { a[i] = '\0'; } trông giống như if (x öö y) ä aÄiÅ = 'Ö0'; å trong bộ ký tự sai. - Ilmari Karonen
Một lưu ý thú vị nữa là Unix (là nền tảng lớn C cưỡi trên) có thể là hệ thống đầu tiên của bất kỳ ý nghĩa nào (và có thể là tổng thể đầu tiên) về giá trị chữ cái mặc định cho chữ thường hơn là chữ hoa. Mặc dù tôi đã không nhìn thấy bằng mắt của mình nhiều hệ thống đương đại, tôi nghĩ đây là một dấu hiệu thực sự của sự tinh tế. Bên cạnh đó thực sự là hệ điều hành khá phong nha, Unix cũng đã chuyển đổi chữ hoa của bạn thành thấp hơn, chứ không phải ngược lại. Những người đó thật sự rất tuyệt. - DigitalRoss
Câu chuyện hài hước tôi phải nói với bạn ... trình biên dịch XL Fortran của máy trạm IBM RS / 6000 được phát triển từ trình biên dịch XL C. Trong một vài bản phát hành đầu tiên, họ vô tình để lại trong quá trình xử lý dấu vết, vì vậy có một số chuỗi ký tự Fortran hợp pháp (trong một chuỗi chữ, IIRC) bị hiểu nhầm là chữ C, dẫn đến một số lỗi thú vị! - Phil Perry


Đó là một C trigraph. ??! Là |, vì thế ??!??! là nhà điều hành ||


140
2017-10-19 16:58



tại sao ai đó nên sử dụng ??! thay vì | ??? / - Fatemeh Karimi
Trigraph đến từ một khoảng thời gian mà một số bàn phím không có tất cả các phím mà họ có bây giờ. Nó cũng đi khi một số trình soạn thảo văn bản dành riêng các ký tự đặc biệt cho những điều đặc biệt. Nó chủ yếu là một di tích của quá khứ và một kẻ lừa đảo quizz;) - Joel Falcou


Như đã nêu ??!??! về cơ bản là hai trigraphs (??! và ??! một lần nữa) đúc với nhau để được thay thế dịch sang ||, tức là Hợp lý HOẶC, bởi bộ tiền xử lý.

Hình ảnh sau đây có chứa tất cả các dấu vết sẽ giúp phân biệt các kết hợp trigraph thay thế:

enter image description here (Ảnh chụp từ C: Hướng dẫn tham khảo 5th Edition)

Vì vậy, một dấu vết trông giống như ??(??) cuối cùng sẽ ánh xạ tới [], ??(??)??(??) sẽ được thay thế bằng [][] và như vậy, bạn có được ý tưởng.

Kể từ khi trigraphs được thay thế trong quá trình tiền xử lý, bạn có thể sử dụng cpp để có được một cái nhìn của đầu ra cho mình, sử dụng một cách ngớ ngẩn trigr.c chương trình:

void main(){ const char *s = "??!??!"; } 

và xử lý nó với:

cpp -trigraphs trigr.c 

Bạn sẽ nhận được một đầu ra giao diện điều khiển của

void main(){ const char *s = "||"; }

Như bạn có thể nhận thấy, tùy chọn -trigraphs phải được chỉ định hoặc người nào khác cpp sẽ đưa ra cảnh báo; điều này cho thấy cách trigraphs là một điều của quá khứ và không có giá trị hiện đại khác hơn là những người khó hiểu, những người có thể va vào chúng.


Đối với lý do đằng sau việc giới thiệu các dấu vết, nó được hiểu rõ hơn khi nhìn vào Lịch sử phần của ISO/IEC 646:

ISO / IEC 646 và ASCII tiền thân của nó (ANSI X3.4) phần lớn ủng hộ thực hành hiện có liên quan đến mã hóa ký tự trong ngành viễn thông.

Vì ASCII không cung cấp một số ký tự cần thiết cho các ngôn ngữ khác ngoài tiếng Anh, một số biến thể quốc gia đã được thực hiện mà thay thế một số nhân vật ít được sử dụng với những người cần thiết


80
2018-03-25 02:24



⁺¹ cho bảng các dấu vết khác. - Hi-Angel