Soru C ne yapar? operatör ne yapar?


Buna benzeyen bir C çizgisi gördüm:

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

Doğru bir şekilde derlenmiş ve iyi çalışıyor gibi görünüyor. Bir hata olup olmadığını kontrol ediyor gibi görünüyor ve eğer varsa, onu ele alır. Ama aslında ne yaptığını ya da nasıl yaptığını bilmiyorum. Programcı hatalarla ilgili duygularını ifade etmeye çalışıyor gibi görünüyor.

Ben hiç görmedim ??!??! herhangi bir programlama dilinden önce, ve bunun için herhangi bir yerde belge bulamıyorum. (Google, arama terimleri gibi ??!??!). Ne yapar ve kod örneği nasıl çalışır?


1605
2017-10-19 16:56


Menşei


duygularınızı başka bir şekilde ifade edin, trigraf kullanmayın, insanlar tarafından anlaşılabilen bir kod yazmayın. - David Heffernan
@PeterOlson, nasıl bekliyorsunuz? !ErrorHasOccurred() ??!???! HandleError(); derlemek için? budur ??!  ???  !. Noktası kanıtlıyor mu? - Michael Kjörling
Temiz kodları okumanı tavsiye ederim. ErrorHasOccured () ErrorHasNotOccured () 'a yeniden ayarlanmalı, böylece ünlem işaretini temizlemelisiniz ... tüm bu operatörleri anlayacak zamanı olan! - KadekM
Tercih ederim ErrorHasOccured() && HandleError() kendim. Lua da böyle yapıyor. - Hugo Zink
@KadekM, olumsuzluğun işlev ismine taşınması, temiz kod için değil, tam tersini yapar. - marcelm


Cevaplar:


??! bir tek sesli üç harf grubu Bu çevirir |. Yani diyor ki:

!ErrorHasOccured() || HandleError();

Kısa devre nedeniyle, buna eşdeğerdir:

if (ErrorHasOccured())
    HandleError();

Haftanın gurusu (C ++ ile ilgilenir, ancak burada alakalı), bunu ben seçtim.

Trigraphların Olası Orijini veya @DwB yorumlarda belirtildiği gibi EBCDIC'nin zor olması (muhtemelen) nedeniyle daha olasıdır. Bu IBM developerworks panosunun tartışması bu teoriyi destekliyor gibi görünüyor.

ISO / IEC 9899: 1999 §5.2.1.1'den dipnot 12 (h / t @ Random832):

Trigraph dizileri, Invariant Code Set'de tanımlanmayan karakterlerin girilmesini sağlar.   Yedi bit ABD ASCII kod kümesinin bir alt kümesi olan ISO / IEC 646'da açıklanmıştır.


1320
2017-10-19 16:58



Klavyenin örneğin '|' olmaması durumunda, orijinal olarak gerekliydi. sembolü. İşte ya programcı, kasıtlı olarak can sıkıcı veya bazı tuhaf editörler 'özellikli' - Martin Beckett
Evet, buna eşdeğer if (ErrorHasOccured()) HandleError(). Neyse ki genellikle sadece bu deyim ile perl kodunda karşılaşırsınız. - user786653
Bu zorunlu olarak EBCDIC değil - trigrafları gerektiren karakterler seti, ISO-646'da (yani eski 'ulusal ascii' standartlarında) değişmez olan karakter kümeleriyle neredeyse tam olarak eşleşir. - Random832
Mükemmel okunabilir bir alternatif olurdu ErrorHasOccurred() && HandleError(); Yani, eğer kabuk yazımı için kullanılıyorsa. :) - Yam Marcovic
"Ya ErrorHasOcurred veya HandleError gerekmiyor", @SparkyRobinson olarak okuyun. - Omar Antolín-Camarena


Peki, bu genel olarak neden var, muhtemelen sizin örnekte var olduğundan farklıdır.

Her şey yarım yüzyıl önce bilgisayar kullanıcı arayüzleri olarak basılı iletişim terminallerini yeniden kullanmaya başladı. İlk Unix ve C çağında ASR-33 Teletype oldu.

Bu cihaz, yavaş (10 cps) ve gürültülü ve çirkin ve ASCII karakter kümesinin görünümü 0x5f'de sona erdi, bu yüzden (resme yakından bakın) tuşlardan hiçbiri yoktu:

{ | } ~ 

Trigraflar belirli bir sorunu çözmek için tanımlandı. Buradaki fikir C programlarının ASR-33'te bulunan ASCII alt kümesini ve yüksek ASCII değerlerini kaçırmayan diğer ortamlarda kullanabilmesiydi.

Örneğin aslında iki ??!, her anlam |Yani sonuç ||.

Ancak, C kodunun neredeyse tanım olarak yazdığı insanlar modern ekipmanlara sahipti.1 bu yüzden benim tahminim: Birinin kendini göstermesi ya da eğlendirmesi, Bir tür Paskalya yumurtasını bulmak için kodda bırakarak.

Kesinlikle işe yaradı, çılgınca popüler bir SO sorusuna yol açtı.

ASR-33 Teletype

ASR-33 Teletipi


1. Bu bağlamda, üçlü, ilk buluşan ANSI komitesi tarafından icat edildi. sonra C kaçak bir başarı oldu, bu yüzden orijinal C kodu veya kodlayıcıların hiçbiri bunları kullanamazdı.


355
2017-10-19 21:09



Klavyede ve karakter kümesindeki tek eksik karakterler vakası değil. Commodore 64, otuzlu yaşlarının sonlarında ve yukarı doğru pek çok insana daha aşina olacak gibi görünüyor - görüntülenen karakterde hem yokluklar hem de (muhtemelen bar ve tilde) var - bu durumda "ASCII" ASCII değildi . ECMA-6'da (hemen hemen her zaman ASCII olarak adlandırılıyor, ancak ABD-ASCII değil) 18 bölgeye özgü kod vardı, ancak hangi kodları olduklarını bilmiyorum. Kesin olarak söyleyebileceğim tek şey - İngiliz "ASCII" de, #ile değiştirildi £. Diğer bölgelerde, belki "ASCII" hiçbir parantez vs. - Steve314
Atari 8 bit bilgisayarlar için kullanılan benzer ATASCII karakterleri de {} yanı sıra ~ ve `içermiyordu. - dan04
Görmek bunlar  iki Vikipedi makaleleri. Ben sadece 7-bit ulusal karakterlerin dönemini hatırlamaya yetecek kadar yaşlıyım (yine de karanlık bir köşede durduklarına eminim) ve ilk öğrendiğim C kitabı hakkında uyarmak için gerekenleri buldum. bir şeyin olma ihtimali if (x || y) { a[i] = '\0'; } benziyor if (x öö y) ä aÄiÅ = 'Ö0'; å Yanlış karakter kümesinde. - Ilmari Karonen
Bir başka ilginç tarihsel nota ise Unix'in (üstte yer alan büyük bir platformdu), büyük harf yerine büyük harflere varsayılan alfabetik değerlerin herhangi bir öneminin (ve belki ilk olanın) ilk sistemi olabileceğidir. Kendi gözlerimle pek çok çağdaş sistemi görmemiş olmama rağmen, bunun gerçek bir sofistike işareti olduğunu düşünüyorum. Unix, sadece tek iyi bir işletim sistemi olmanın yanı sıra, büyük harfinizi de tersine değil de aşağıya çevirdi. Bu adamlar çok havalıydı. - DigitalRoss
Söylemem gereken komik hikaye ... IBM RS / 6000 iş istasyonunun XL Fortran derleyicisi XL C derleyicisinden geliştirildi. İlk birkaç sürümde, kazayla trigraph işleminde kalıyorlardı, bu yüzden bazı ilginç hatalara yol açacak şekilde C trigrafları olarak yanlış okunan bazı okunaklı Fortran karakter dizileri (bir harf dizisinde, IIRC) vardı! - Phil Perry


Bu bir C tek sesli üç harf grubu. ??! olduğu |, yani ??!??! operatör ||


140
2017-10-19 16:58



neden birisi kullanmalı? yerine | ??? / - Fatemeh Karimi
Trigraph, bazı klavyelerin sahip oldukları tüm tuşlara sahip olmadığı bir dönemden geliyor. Bazı metin editörleri özel şeyler için özel karakterleri sakladığında da hels. Çoğunlukla geçmişin bir kalıntısı ve bir quizz etkinleştirici;) - Joel Falcou


Daha önce belirtildiği gibi ??!??! aslında iki üç karakterli (??! ve ??! tekrar) değiştirildi ||yani Mantıksal VEYAÖnişlemci tarafından.

Tüm trigraphları içeren aşağıdaki görüntü alternatif trigraph kombinasyonlarını ayırmaya yardımcı olacaktır:

enter image description here (Resimden alındı C: Bir Referans El Kitabı 5. Baskı)

Yani benzeyen bir deneme ??(??) sonunda eşlenecek [], ??(??)??(??) yerini alacak [][] ve böylece fikri anladınız.

Ön işlem sırasında trigraphlar değiştirildiği için kullanabilirsiniz cpp bir aptal kullanarak çıktıyı kendiniz görmek için trigr.c Program:

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

ve ile işleme:

cpp -trigraphs trigr.c 

Bir konsol çıktısı alacaksınız

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

Fark edebileceğiniz gibi, seçenek -trigraphs belirtilmelidir ya da cpp uyarı verecek; bu nasıl gösterir Trigraflar geçmişte bir şeydir ve bunlara çarpacak kişileri kafa karıştırıcıdan başka modern bir değere sahip değildir..


Trigrafların tanıtımının ardındaki mantık açısından bakıldığında, Tarihçe bölümü ISO/IEC 646:

ISO / IEC 646 ve onun öncülü ASCII (ANSI X3.4), telekomünikasyon endüstrisindeki karakter kodlamaları ile ilgili mevcut uygulamaları büyük ölçüde destekledi.

ASCII, İngilizce dışındaki diller için gerekli olan bir dizi karakter sağlamamıştır. ihtiyaç duyulanlarla daha az kullanılan karakterlerin yerini alan bir dizi ulusal varyant yapıldı.


80
2018-03-25 02:24



Diğer trigrafların tablosu için ⁺¹. - Hi-Angel