Ne yapar ??!??! operatör C yapmak?


1990

Şuna benzeyen bir C çizgisi gördüm:

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

Doğru derlenmiş ve iyi çalışıyor gibi görünüyor. Bir hatanın meydana gelip gelmediğini kontrol ediyor gibi görünüyor ve eğer varsa, ele alıyor. Ama aslında ne yaptığını ya da nasıl yaptığını gerçekten bilmiyorum. Programcı hatalarla ilgili duygularını ifade etmeye çalışıyor gibi görünüyor.

Daha önce hiç ??!??!bir programlama dilinde hiç görmedim ve bunun için hiçbir yerde belge bulamıyorum. (Google gibi arama terimlerine yardımcı olmaz ??!??!). Ne işe yarar ve kod örneği nasıl çalışır?


44
@PeterOlson, nasıl !ErrorHasOccurred() ??!???! HandleError();derlemeyi umuyorsunuz ? İşte ??! ??? !. Ne demek oluyor?
CVn

31
Temiz kod okumanızı tavsiye ederim. ErrorHasOccured (), ErrorHasNotOccured () öğesine göre yeniden düzenlenmelidir, böylece ünlem işaretini temizler ... tüm bu operatörleri anlamak için kimin zamanı var ??!
KadekM

17
ErrorHasOccured() && HandleError()Kendimi tercih ederim. Lua da böyle yapar.
Hugo Zink

76
@KadekM, olumsuzlamanın işlev adına taşınması, temiz kod için değil, tam tersi anlamına gelir.
marcelm

14
Arama motorları ile ölümüne kavga ettikten sonra burada bulunan herkes için bir not: SymbolHound , sembolik aramalarda yardımcı olabilir.
Jakob

Yanıtlar:


1579

??!Bir olan sesli üç harf çevirir |. Yani diyor ki:

!ErrorHasOccured() || HandleError();

kısa devre nedeniyle aşağıdakilere eşittir:

if (ErrorHasOccured())
    HandleError();

Haftanın Guru (C ++ ile ilgilenir ama burada alakalı), bunu aldım.

Yorumlarda olası trigrafların veya @DwB'nin belirttiği gibi, EBCDIC'in zor olması nedeniyle daha olasıdır (tekrar). IBM geliştirici çalışmaları panosundaki bu tartışma bu teoriyi desteklemektedir.

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

Üçgen dizileri, yedi bitlik ABD ASCII kod kümesinin bir alt kümesi olan ISO / IEC 646'da açıklandığı gibi Değişmez Kod Kümesinde tanımlanmayan karakterlerin girilmesini sağlar.


378
Klavyenizde örneğin '|' olmaması durumunda başlangıçta trigraflar gerekiyordu sembolü. Burada ya programcı kasıtlı olarak sinir bozucu ya da tuhaf bir editör 'özelliği'
Martin Beckett

36
Evet, buna eşdeğer if (ErrorHasOccured()) HandleError(). Neyse ki genellikle bu deyimle sadece perl kodunda karşılaşırsınız.
user786653

22
Mutlaka EBCDIC olması gerekmez - trigraf gerektiren karakterler kümesi, ISO-646'da (yani eski 'ulusal ascii' standartları) değişmeyen karakter kümesiyle neredeyse tam olarak eşleşir.
Random832

52
Mükemmel okunabilir bir alternatif ErrorHasOccurred() && HandleError();, komut dosyasını kabuklamaya alışkın olmanızdır. :)
Yam Marcovic

18
"Ya HataHasOcurred ya da HandleError gerekir", @SparkyRobinson olarak okuyun.
Omar Antolín-Camarena

453

Bunun genel olarak neden var olması muhtemelen örneğinizde var olduğundan farklıdır.

Her şey yarım yüzyıl önce bilgisayar kullanıcı arabirimleri olarak basılı iletişim terminallerinin yeniden konumlandırılmasıyla başladı. İlk Unix ve C döneminde ASR-33 Teletype'tı.

Bu cihaz yavaş (10 cps) ve gürültülü ve çirkin ve ASCII karakter setinin görünümü 0x5f'de sona erdi, bu yüzden anahtarların hiçbirine (resme yakından bakın) sahip değildi:

{ | } ~ 

Trigraflar belirli bir sorunu düzeltmek için tanımlandı. Fikir, C programlarının ASR-33'te bulunan ve yüksek ASCII değerlerini eksik olan diğer ortamlarda bulunan ASCII alt kümesini kullanabilmesiydi.

Örneğiniz aslında ??!her anlamdan ikidir |, sonuçtur ||.

Ancak, neredeyse tanım gereği C kod yazarken insanlar, modern ekipman vardı 1 benim tahminim bu yüzden: Birisi, gösteriş veya kendilerini eğlendirirken bulmak için kod Paskalya yumurtası bir tür bırakarak.

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

ASR-33 Teletipi

                                            ASR-33 Teletipi


1. Bu nedenle, trigrafiler, C'nin kaçak bir başarı haline gelmesinden sonra ilk kez toplanan ANSI komitesi tarafından icat edildi , bu nedenle orijinal C kodu veya kodlayıcıların hiçbiri bunları kullanmazdı.


18
Klavyede ve karakter setinde eksik karakterlerin tek örneği değil. Commodore 64, otuzlu yaşlarının sonlarında ve daha fazlasında birçok insana daha tanıdık gelecek - görüntülenen karakter hem parantez (hem de muhtemelen bar ve tilde) yoktu - bu durumda "ASCII" ASCII değildi . ECMA-6'da (neredeyse her zaman ASCII denir, ancak US-ASCII değil) 18 bölgeye özgü kod vardı, ancak bunların hangi kodlar olduğunu bilmiyorum. Kesinlikle söyleyebileceğim tek şey - İngiliz "ASCII" #de değiştirildi £. Diğer bölgelerde, belki "ASCII" nin diş telleri vb.
Yoktu

7
Atari 8-bit bilgisayarlar için benzer ATASCII karakter setinde {} ve ~ ve `karakterleri yoktu.
dan04

42
Bu iki Wikipedia makalesine bakın . 7 bitlik ulusal karakter setlerinin çağını hala hatırlayabilecek kadar yaşlıyım (hala karanlık, karanlık köşelerde hala devam etmelerine rağmen eminim) ve ilk öğrendiğim kitap C'yi uyarmak için gerekli buldu yanlış karakter setinde if (x || y) { a[i] = '\0'; }gibi görünme olasılığı if (x öö y) ä aÄiÅ = 'Ö0'; å.
Ilmari Karonen

9
Bir başka ilginç tarihsel not, Unix'in (C'nin üzerinde çalıştığı büyük platform olan), alfabetik değerlerin büyük harf yerine küçük harfe dönüştürülmesi için herhangi bir öneme sahip (ve belki de ilk toplam) ilk sistem olabileceğidir. Her ne kadar kendi gözlerimle pek çok çağdaş sistem görmemiş olsam da, bunun gerçek bir sofistike işaret olduğunu düşünüyorum. Gerçekten tek iyi işletim sistemi olmanın yanı sıra, Unix de büyük harfinizi tersine değil, büyük harfinize dönüştürdü. O adamlar çok iyiydi.
DigitalRoss

16
Komik hikaye size söylemeliyim ... IBM RS / 6000 iş istasyonunun XL Fortran derleyicisi XL C derleyicisinden geliştirilmiştir. İlk birkaç sürümde, trigraf işlemede yanlışlıkla bırakıldılar, bu yüzden C trigrafı olarak yanlış yorumlanan bazı ilginç hatalara yol açan bazı yasal Fortran karakter dizileri (bir gerçek dizgide, IIRC) vardı!
Phil Perry

166

Bu bir C üçgeni . ??!olduğunu |, bu nedenle ??!??!operatörüdür||


5
trigraf, bazı klavyelerin şu anda sahip oldukları tüm tuşlara sahip olmadığı bir dönemden geliyor. Bazı metin düzenleyicileri özel şeyler için özel karakterler ayırdığında da cehennem olur. Çoğunlukla geçmişin bir kalıntısı ve bir
sınav kolaylaştırıcısı

5
Çünkü görünüşe göre bazı klavyelerde "|" yok bu yüzden bazı kişilerin, ihtiyaç duydukları sembolleri veren bir trigraf oluşana kadar klavyeyi tekrar tekrar çalmaktan başka seçeneği yoktur.
Baykuş

Ve sonra <iso646.h>başlık dosyası var.
David R Tribble

149

Zaten belirtildiği gibi ??!??!, esasen iki üç karakterli ( ??!ve ??!yine) için değiştirilir tercüme olsun bir araya mushed ||yani mantıksal VEYA önişlemci tarafından,.

Her trigrafı içeren aşağıdaki tablo, alternatif trigraf kombinasyonlarını netleştirmeye yardımcı olmalıdır:

Trigraph   Replaces

??(        [
??)        ]
??<        {
??>        }
??/        \
??'        ^
??=        #
??!        |
??-        ~

Kaynak: C: Bir Referans Kılavuzu 5. Baskı

Gibi görünüyor ki TriGraph ™ mod seçimini Yani ??(??)nihayetinde için eşler [], ??(??)??(??)yerini alacak [][]ve böylece, anladınız.

Ön işleme sırasında trigraflar değiştirildiğinden cpp, aptal bir trigr.cprogram kullanarak çıktıyı kendiniz görmek için kullanabilirsiniz :

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

ve aşağıdakilerle işlenmesi:

cpp -trigraphs trigr.c 

Konsol çıktısı alırsınız

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

Fark edebileceğiniz gibi, seçenek -trigraphsbelirtilmelidir, aksi cpptakdirde bir uyarı verilir; bu, trigrafların nasıl geçmişte kaldığını ve bunlarla karşılaşabilecek insanları şaşırtmaktan başka modern bir değeri olmadığını gösterir .


Trigrafların getirilmesinin arkasındaki mantığa gelince , ISO / IEC 646'nın tarih bölümüne bakıldığında daha iyi anlaşılır :

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

ASCII, İngilizce dışındaki diller için gereken bir dizi karakter sağlamadığından, daha az kullanılan bazı karakterleri gerekli olanlarla değiştiren bir dizi ulusal varyant yapılmıştır .

(benimkini vurgula)

Bu nedenle, bazı ulusal değişkenlerde gerekli olan bazı karakterler (bir trigrafın olduğu karakterler) değiştirildi. Bu, diğer varyantların hala sahip olduğu karakterlerden oluşan trigrafları kullanarak alternatif temsile yol açar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.