DOĞRU ve YANLIŞ makroların garip tanımları


300

Bir kodlama kitabında aşağıdaki makro tanımlarını gördüm.

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

Orada bir açıklama yoktu.

Lütfen bunların nasıl TRUEve nasıl çalışacağını açıklayın FALSE.


63
TRUE'u

160
Bunun, bu ifadelerin etrafında köşeli parantez olmadan korkunç bir fikir olduğunu unutmayın. Bunun kötü bir fikir anlamına ile onları, ama sadece ayıklama uzun bir gece için soruyorsun olmadan.
TartanLlama

70
Referans verdiğiniz kodlama kitabını öğrenebilir miyim?
artm

47
Umarım bu kitap bunu kötü ya da kasıtlı olarak belirsiz bir kod örneği olarak içerir.
Jon Hanna

31
@Daniel: Başka bir fikir rand ()% 2, MAYBE'yi rand ()% 2 olarak tanımlamak olacaktır, bu yüzden bazen == DOĞRU ve bazen == YANLIŞ.
Kaiserludi

Yanıtlar:


380

Bakalım: '/' / '/'araçlar charliteral /bölünmesiyle, charedebi '/'kendisi. Sonuç makul olanıdır TRUE.

Ve kendisinden çıkarılan gerçek '-' - '-'anlamına gelir . Bu sıfır ( ).char'-'FALSE

Bununla ilgili iki sorun var: birincisi, okunamıyor. Kullanmak 1ve 0kesinlikle daha iyidir. Ayrıca, TartanLlama ve KerrekSB'nin de belirttiği gibi, eğer bu tanımı kullanacaksanız, lütfen etraflarına parantez ekleyin, böylece herhangi bir sürpriziniz olmaz:

#include <stdio.h>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

int main() {
        printf ("%d\n", 2 * FALSE);
        return 0;
}

Bu, chardeğişmez değerin değerini yazdıracaktır '-'(sistemimde 45).

Parantez ile:

#define TRUE  ('/'/'/')
#define FALSE ('-'-'-')

bir doğruluk değerini bir tamsayı ile çarpmak pek mantıklı olmasa da, program doğru olarak sıfır yazdırır, ancak bu, makrolarınızı parantez içinde almazsanız sizi ısıtabilecek beklenmedik hataların bir örneğidir.


6
Lanet olsun anlamak için çok şey aldım: hatta glifler gibi garip bir şey olduğunu düşündüm ... xD bilmiyorum
Luis Masuelli

8
Aslında doğruluk değeriyle çarpmak mantıklıdır. İnceleme girintisi için * should_indent, dallanma olmadan end_indent olup olmamasına bağlı olarak 0 veya girinti ile sonuçlanır. (Sanırım bu kötü bir örnek, metinle çalışırken tek dallanma önemli değil, (Bu tekniği gölgelendiricilerde ve
XPATH'de gördüm

2
Alpedar - ancak kavramsal olarak ve matehmatik olarak bunu yapmak için anlam ifade etmez - bu durumda bir tamsayı ifile çarpmak yerine kullanmak daha açık (ve kavramsal olarak mantıklı) olacaktır TRUE.
Jay

4
Harika bir açıklama. Altın rozet al!
Michael Hampton

2
Mantıksal olumsuzlama şu şekilde uygulanabilir notx = TRUE- x;ve iyi çalışır. Bunun dışında TRUE-FALSE-44 (ASCII varsayarak)
Hagen von Eitzen

89

Bu sadece yazmanın başka bir yolu

#define TRUE 1
#define FALSE 0

İfade '/'/'/', '/'sonuç olarak 1 verecek olan karakter değerini kendi başına böler .

İfade '-'-'-', '-'kendisinin karakter değerini özetleyecek ve sonuç olarak 0 verecektir.

Tüm defineifadelerin etrafındaki köşeli parantezler eksiktir, bu da bu makroları kullanarak kodda hatalara neden olabilir. Jay'in cevabı bunu çok iyi karşılar.

Köşeli parantezlerin unutulmasının zararlı olabileceği "gerçek hayat" senaryosunun bir örneği, bu makroların bir C stili döküm operatörü ile birlikte kullanılmasıdır. Birisi bu ifadeleri boolC ++ dilinde yayınlamaya karar verirse, örneğin:

#include <iostream>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

int main() {
    std::cout << "True: " << (bool) TRUE << std::endl;
    std::cout << "False: " << (bool) FALSE << std::endl;
    return 0;
}

İşte elde ettiklerimiz:

True: 0
False: -44

Yani (bool) TRUEaslında hiç değerlendirirsiniz falseve (bool) FALSEhiç değerlendirirsiniz true.


4
Örnek güzel bir örnek :)
Kit Fisto

44

Yazmaya eşdeğerdir

#define TRUE 1
#define FALSE 0

İfadenin '/'/'/'gerçekte yaptığı, karakteri /(sayısal değeri ne olursa olsun) tek başına bölmektir, böylece olur 1.

Benzer şekilde, ifade '-'-'-'karakteri -kendisinden çıkarır ve olarak değerlendirir 0.

Yazmak daha iyi olur

#define TRUE ('/'/'/')
#define FALSE ('-'-'-')

diğer yüksek öncelikli operatörlerle kullanıldığında değerlerin yanlışlıkla değiştirilmesini önlemek için.


5
LOL! Bu yüzden makrolar uygun şekilde parantez içine alınmalıdır.
0605002

Bir kürede 3 hak ve aynı yerde
olursunuz

KerrekSB Hayır, ama üç lefts do :)
Tim Long

33

Jay zaten bu ifadelerin değerleridir neden cevap 0ve 1.

Tarih uğruna, bu ifadeler '/'/'/'ve 1984'te 1. Uluslararası Gizli C Kodu Yarışması'nın'-'-'-' girişlerinden birinden gelir :

int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}

( Buradaki programa bağlantı , yukarıdaki IOCCC sayfasında bu programın ne yaptığına dair bir ipucu var.)

Ayrıca, bu ifadeleri gizlenmiş makrolar olarak doğru hatırlıyorsam TRUEve FALSEaynı zamanda Don Libes (1993) tarafından yazılan "Gizli C ve Diğer Gizemler" kitabında da yer aldı.


7

İçin makro yazmak için bu komik yolu Trueve False.

Birçok açıklama temin edilmiştir olarak /(ASCII göre) vasıtaları, bir 1 bayt sayısının tek başına bölünmüş zaman vermek 1olarak tedavi olacak Truebenzer şekilde ve -bu vermek aynı değere çıkarılır zaman bir bayt sayısı tekrar edilir 0olarak yorumlanacaktırfalse

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

dolayısıyla /veya -istediğimiz herhangi bir karakterle değiştirebiliriz , örneğin:

#define TRUE  '!'/'!'
#define FALSE 'o'-'o'

Orijinal ifadeyle aynı anlamı koruyacaktır.


6

Doğru ile başlayalım. Sen olarak okuyabilir '/' / '/', hangi vasıta "karakteri '/' karakteri '/' bölü". C'deki her karakter sayısal bir değer (bir bayt üzerinde) olduğundan, "/ 'karakterinin ASCII değerinin aynı karakterin ASCII değerine bölünmesi" olarak okunabilir, yani 1 (açıkçası, x / x 1) 'dir. Dolayısıyla, TRUE1'dir.

İçin FALSE , aynı mantık: '-'-'-'okur '-' - '-', yani "- 'ASCII değeri eksi 0 -' - 'ASCII değeri", dolayısıyla 0'dır FALSE.

Bu bariz olanı belirtmenin kötü bir yoludur.


7
Bunun ASCII ile bir ilgisi yok.
Kerrek SB

6
@Fabien: ASCII'ye bağlı değil . (ASCII'de olduğu gibi) veya (EBCDIC'de olduğu gibi) veya başka bir değer '/'/'/'için geçerli herhangi bir karakter kümesi için 1'dir . '/' == 47'/' == 97
Keith Thompson

4
@Pawel: Bir uyumlu C uygulaması eşleyemezsiniz '/'için 0. Bu değer null karakter için ayrılmıştır.
Keith Thompson

2
Bilgiçlik yapıyorsun.
Matheus208

3
@ Matheus208 Pawel bilgiçlik taslayan olsaydı, o zaman bu ('-'-'-') noktası belirsiz bir duruma dayandığı için; Keith'in sözlerini bilgiçlikçilik olarak tanımlamak daha fazla olabilir ('/' / '/') ama onlara "açıklayıcı" diyorum (ve eklenen suratlarla "bilgiçlik" kesinlikle '/' - '/' görünüyor). Birlikte alınan yorumların bilgiçlikçi olarak adlandırılabileceği ('-' / '-') olabilir, ancak 1) bu alanda biraz zorunlu değil mi? 2) beni düşündürdüler; ve 3) Bazı şeylerde benden daha netim. Ve evet, sanırım kendim bilgiçlik yapıyorum! (Ama "bilgiçlik" ne demek istediğimi daha net! ;-)
Zhora
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.